OmniAICreator/Qiita-1.07M huggingface dataset:
Rails未経験だが、ProgateのRailsコースを修了して類似アプリを作ってみた話

ほぼ未経験からprogateを続けて3ヶ月、HTML&CSSコース、JS、jQuery、RubyおよびRuby on Rails5コースを終えて、ドットインストールのBootstrapコースも終えたので、復習も兼ねてRails5コースで作成したtwitter風のアプリの類似クソアプリを作ったので晒します。

[どうでもいいねSNS](https://dodemo-fav.herokuapp.com/)


どんなアプリ？
---
どうでもイイことを呟く感じのアプリです。


トップ画面(ログイン画面とユーザ登録画面です)
![スクリーンショット 2018-12-16 17.52.02.png](https://qiita-image-store.s3.amazonaws.com/0/238856/daf93c92-d711-3b10-2869-5cf14bcb3d48.png)


メイン画面
簡単なことを呟けます。"どうでもイイネ"ボタンがありますので、それで"どうでもイイね"することができます。
![画面収録 2018-12-16 17.37.18.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/238856/2a3a840a-3a16-7cb2-e94f-20eb1637bcef.gif)
編集、削除もボタンがあり編集できます。


また、ユーザ情報も編集できます
ヘッダ部のユーザ情報を押すことで遷移します。
またサムネ画像もここで編集することができます。
![スクリーンショット 2018-12-16 17.54.15.png](https://qiita-image-store.s3.amazonaws.com/0/238856/8e3a575f-636a-600b-805c-47ce55dbbd5f.png)

最後に管理人のみ見れる機能として、ユーザ一覧管理機能も作ってます
![スクリーンショット 2018-12-16 18.02.45.png](https://qiita-image-store.s3.amazonaws.com/0/238856/c99f8702-bb38-892e-ff87-38de6cc8d2ff.png)





経緯
---
自分が思う、Twitter上の巷のTLの割合はこんな感じかなと思います
![TL上の割合.jpg](https://qiita-image-store.s3.amazonaws.com/0/238856/2a5e85b3-4169-7a11-c7da-1cb635fdbf47.jpeg)

また呟くときも、"どうでもイイんだけどね"って思って呟く場合もあるかと思います。
でもtwitterには"どうでもイイね"ボタンがない・・・

<font color="LightSalmon">**なら作るか**</font>

という感じで作りました。

どうやって作ったか
---
Javaは業務で触っていたが、RubyやRailsは未経験の状態から2018年の8月からprogate勉強を始めて、それからProgate学習サービスにお世話になっています。本当にありがたいです。

サーバー:
プラットフォームについては定番の一つである[Heroku](https://jp.heroku.com/)を使用しています。
またソース管理はこれまた定番のGitHubです。
一応このプロジェクトのリポジトリです。
https://github.com/rtjob/posts_test

サーバサイド:
Railsコースのほぼコピーです。
DBはNoSQLを業務で使ったことなく、使ってみたかったので、それであるMongoDBを使用しています。
MongoDBについては下記が概要として詳しいです
[世界第4位！最有力NoSQLデータベースMongoDBはRDBとどう違うのか？特徴と使い分け](https://tracpath.com/works/development/nosql_mongodb/)

フロント:
デザインの経験もなくても、手軽にそれっぽく作れたりレスポンス対応もできる
[Bootstrap](https://getbootstrap.com/)を使用しています。
Bootstrapについては、ドットインストールに講座が公開されています。
[Bootstrap 4入門](https://dotinstall.com/lessons/basic_twitter_bootstrap_v5)

あとロゴについては[@デザインTipsさん](https://twitter.com/tips_bot)のツイートが役に立ちました。ありがとうございます。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ロゴを作るとき、なんか寂しかったら適当に２行目を作ると大抵それっぽくなります。<br>だいたいの書体でうまくいきます。<br><br>書く内容はなんでもよくて、漢字のタイトルだったら読みでもいいし、英訳したタイトルでもいいし、サークル名でもなんでも大丈夫です。 <a href="https://t.co/QflvJvyknX">pic.twitter.com/QflvJvyknX</a></p>&mdash; デザインTips@1日目 西に20b (@tips_bot) <a href="https://twitter.com/tips_bot/status/1029394278236082178?ref_src=twsrc%5Etfw">2018年8月14日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


苦労点は
---
正直全部・・・という感じですが、Progateで学習して、それをアプリにフィードバックして、エラーが出たらprogateで復習orググる。のループです。エラーはRailsでのエラーよりも、MongoDB周りのエラーが多かった印象です。MongoDBとRailsは相性が微妙な印象です。。あとデザイン・・・


今後は
---
余力が出てくれば
- twitter連携機能  
と  
- サムネがユーザ作成時はデフォルトだが、それを選べるようにする。
- メールの認証

的なことは考えてます。

あとは画像もHerokuに格納しているので、容量大きくなったら、画像のみAWS S3に移すことも検討ですね。

最後に
---
progateのRailsコースが11コースあり、時間かかるかなっと思ってましたが
こちらは土日を中心に勉強して、1ヶ月もいらなかったですが
この規模のアプリ作りでも環境構築からそれっぽくするまで1,2ヶ月ほど時間がかかります。(自分が要領悪いだけかもですが)慣れですかね。。。

以上です。
Railsで複数項目での order  by を簡単に記述する

複数項目を条件にしたソートをActiveRecordで記述する場合に毎回検索して調べていましたが非常に簡単な方法がありました。
`order` を項目の数だけ記述すればいいのです。

```ruby
User.order(:group).order(:name)
```

降順でソートする場合は以下のように書きます。

```ruby
User.order(:group).order(birth: :desc)
```

Ruby on Rails Guides に記載されているのに何故か広まっていませんね。

[Active Record クエリインターフェイス - 3 並び順](https://railsguides.jp/active_record_querying.html#%E4%B8%A6%E3%81%B3%E9%A0%86)
ElmのBrowser.*の使い分け

## 概要
Browser.sandbox, element, document, applicationの違いは？どう使い分けるの？
という疑問にふんわり答えます


2回くらい聞かれたので書いておきます
詳しいことはElm Guideやpackage documentをみればいいので詳しいこともコードも、参考リンクも載せません

Elmは0.19
elm/browserは1.0.1

## そもそも使い分けるものじゃない

基本的にはできることが増えていく感じだと思ってください
増える機能を使いたいなら上げる感じです

### sandboxより前

実はelmのmainはHtml型でも受け入れてくれます

```elm
main : Html msg
main = Html.text "Hello, world"
```

コード書いちゃった…。最初にちゃんと静的ハローワールドやった人なら知ってるよって感じでしょうが意外と忘れます
Stringはだめです

### sandbox

純粋な世界にようこそ！
CmdとSubが使えません。いわゆる副作用ですね
とはいえユーザーのクリックとか入力とか取れるので何もできないわけではないです。何が純粋だ

具体的には乱数とかAPIたたくとかJSとやりとりするとかができません
あなたのアプリがAPIたたくわけではないならこれでいいのでは？

### element

APIがたたけるよ！
ついに外界とやり取りできるようになりました
あなたが望むのならJSで起動するときにFlagsと呼ばれる初期値みたいなものを渡すことができます。またサイコロもふれるし、ユーザーのアクションの５秒後に何か起こすことだってできます

CmdとSubの概念は最初はなじみのないものでしょうからちゃんとガイドを読むといいと思います

### document

このDOMの世界はわたしのものです！
今までは起動時にあるnodeを渡すことでそのnode下をマウントしていましたが、ここからはbodyタグ直下をマウントします
ついでにtitleタグをいじれるようになります。

> 注意：documentとapplicationではReactアプリケーションにElmを埋め込むということができなくなります
主導権が完全にElmになるので、ElmにReactを埋め込むならできます

### application

ルーティングしたい

あなたのアプリケーションでルーティングをしたいなら間違いなくこれです。
elementではルーティングはできません。つまりElmが主導権を握る必要があります。

applicationではaタグでのリンククリックがElmのランタイムに捕まえられ、updateで処理することができます。pushしてもいいですし、loadしてもいいです。あなたのコード次第です。
特別なタグ（NavLinkみたいな）を使う必要はありません


## 終わり

ガイドとパッケージドキュメント読んでください
Python 多次元 dict／collections.Mapping のキーを list に変換する

辞書の要素に辞書を持つような多次元辞書のキーをリスト化する。
親要素のキーと子要素のキーを連結する。

イメージは以下。

```python:
# 変換元
{
    '親': {
        '子1': 1,
        '子2': [1, 2, 3, 4],
        '子3': {
            '孫1': 1,
            '孫2': 2,
            '孫3': 3
        }
    }
}

# 変換結果
[
    '親.子1',
    '親.子2',
    '親.子3.孫1',
    '親.子3.孫2',
    '親.子3.孫3'
]
```


## 前提条件

* OS： CentOS Linux release 7.5.1804 (Core)
* Python： Python 3.6.5

## ソースコード

```python:
import collections
import sys
import json


def convert_dict_to_list(dict_, path_delimiter='.', path=''):
    """dict／collections.Mappingをlistに変換する。

    Args:
        dict_ (dict or collections.Mapping): 変換元。
        path_delimiter (str): 多次元構造の場合の区切り。
        path (str): 値名に付与する文字列。

    Returns:
        list: 変換結果。
    """

    list_ = []
    is_top = len(path) == 0

    for k, v in dict_.items():
        if is_top:
            str_ = k
        else:
            str_ = '{}{}{}'.format(path, path_delimiter, k)

        if isinstance(v, dict) or isinstance(v, collections.Mapping):
            list_.extend(convert_dict_to_list(
                    v,
                    path_delimiter,
                    str_))
        else:
            list_.append(str_)

    return list_


def main():
    with open(sys.argv[1]) as f:
        json_data = json.load(f)

    list_ = convert_dict_to_list(json_data)
    print(list_)


if __name__ == '__main__':
    main()
```

## 実行サンプル

元データ（JSON文字列）

```json:
{
  "grp1": {
    "param1": "aaa",
    "param2": "bbb",
    "param3": 10,
    "param4": true,
    "param5": false,
    "grp1-1": {
      "param11": "aaa",
      "param12": "bbb",
      "param13": 10,
      "param14": true,
      "param15": false
    }
  }
}
```

変換結果

```shell:
['grp1.param1', 'grp1.param2', 'grp1.param3', 'grp1.param4', 'grp1.param5', 'grp1.grp1-1.param11', 'grp1.grp1-1.param12', 'grp1.grp1-1.param13', 'grp1.grp1-1.param14', 'grp1.grp1-1.param15']
```
atcoder ABC49 D問題

Union-Find木を使わないと解けない問題だったので、解法をメモ

https://beta.atcoder.jp/contests/abc049/tasks/arc065_b

問題は、グラフを２通り作り両方において、ある辺とある辺が連結している個数を求める問題である。はじめは深さ優先探索をしていたが頂点の個数が多いのでMLEやTLEを起こしてしまうので、Union-Find木で連結の判定をしなければならない。Union-Find木の基本的な実装は下の通り。




```java
class UnionFind{
	int[] parent;        //親ノード
	public UnionFind(int N){
		this.parent = new int[N];       //初期化
		for(int i = 0; i < N;i++){
			parent[i] = i;
		}
	}
	public int root(int x){			//根要素を取得
		if(parent[x] == x){			//初期状態
			return x;
		}else{
			return parent[x] = root(parent[x]);    	//再帰によって根を取得
		}
	}
	public void unite(int x,int y){ 	//統合メソッド
		if(same(x,y)){					//同じ根なら終了
			return;
		}
		int xroot = root(x);
		int yroot = root(y);
		parent[xroot] = yroot;			//統合
		return;

	}
	
	public boolean same(int x,int y){			//根が同じか（同じグループに属しているか）を判定
		return(root(x) == root(y));
	}
}

```
[Firebase]Firebaseのdatabase

FirebaseのDatabaseを初めて使うようになりました。
それでFirebaseのDatabaseの使い方を書きます!
#データ構造
データ構造がJSONツリーです。
SQLデータベースと違ってテーブルやレコードがないです。
ユーザーIDまたは自分の指定した名前をキーで使うできて、push()を使用して自動的に指定できます。
データは次のような形で保存されます。
```{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { ... },
    "eclarke": { ... }
  }
}```
#データの読み取りと書き込み
データベースでデータの読み書きを行うには、firebase.database.Reference のインスタンスが必要です。
```// Get a reference to the database service
var database = firebase.database();
```
<dl><dt>1. 書き込み</dt>
<dd>データ保存方法は「.set」と「.push」があります。
「.set」を使うと、指定位置で下位ノードを含むすべてのデータが削除されて、データが保存されます。
```database.ref('test/').set({"country": "Korea", "location": "seoul"});```
「.push」を使うと項目を追加し続けることができる。
```database.ref('test/').push({"country": "Japan", "location": "tokyo"});
database.ref('test/').push({"country": "England", "location": "london"});```
</dd>
<dt>2. 読み取り</dt>
<dd>データリストで読むことです。 
```var databaseRef = firebase.database.ref('test/');
databaseRef.on('value', function(data){
	console.log(data.val());
});```</dd></dl>
#データの修正
データ修正をする時はキーの値を知らなければなりません。
```//firebase.database.ref('test/' + [キーの値]).update([修正する値]);
databaseRef = firebase.database.ref('test/4r1oqVyxV0HMpwfgUz4T').update({
location: "paris"
});```
#データの削除
削除は「.remove」を使います。
```databaseRef = firebase.database.ref('test/4r1oqVyxV0HMpwfgUz4T').remove();```

---
[参照] Firebase (https://firebase.google.com/docs/database/web/read-and-write)
Plug.ErrorHandlerとPlug.DebuggerでPhoenixの標準のエラーをカスタマイズする

*この記事は[「Elixir Advent Calendar 2018」](https://qiita.com/advent-calendar/2018/elixir)の16日目です*

1年弱PhoenixでAPIサーバーを書いてきた中で得た、Phoenixが標準で返すエラーレンスポンスについての知見をご紹介します

# 前提
この記事での「標準のエラー」は、Phoenixが勝手にハンドリングしてくれる種のエラーとします。ルーティング未定義や文法ミスで怒られてる時に出るものです。
(最適な表現があれば教えてください🙇‍♂️)

# エラー時のレスポンスのカスタマイズ
例えばルーティング未定義のパスにアクセスした際、デフォルトだとそれぞれのバージョンで以下のようなレスポンスが返ります(`MIX_ENV=dev`だとデバッグ画面が出ます)

```elixir:Phoenix1.4
"Not Found"

# phx.newの際に '--no-html --no-webpack' を付けた場合
# (吐き出される lib/views/error_view.ex が変わる)
{"errors":{"detail":"Not Found"}}
```

```elixir:Phoenix1.3以下
"Page not found"
```

ここの形式を丸ごと上書きしたかったりする場合は以下のように `Plug.ErrorHandler.handle_errors` を自分で書いてRouter内でuseします

```elixir:lib/hoge_web/router_err_handler.ex
defmodule HogeWeb.RouterErrHandler do
  @moduledoc ""

  defmacro __using__(_) do
    quote do
      use Plug.ErrorHandler

      def handle_errors(conn, %{reason: %Phoenix.Router.NoRouteError{}}) do
        conn
        |> put_status(404)
        |> json(%{message: "Not Found"})
      end

      def handle_errors(conn, _) do
        conn
        |> put_status(500)
        |> json(%{message: "Internal Server Error"})
      end

    end
  end
end
```

```elixir:lib/hoge_web/router.ex
defmodule HogeWeb.Router do
  use HogeWeb, :router
  use HogeWeb.RouterErrHandler
  # ...
```

しかし、これらは `MIX_ENV=dev` の時のデバッグ画面も上書きすることに注意してください

# デバッグ画面をかっこよくしてみる
あまりにも使いどころがありませんが、`MIX_ENV=dev`の際のデバッグ画面をカスタマイズする方法が一応用意されています

## こんな感じ
(名取さなちゃんチック)
![1544951627635.jpg](https://qiita-image-store.s3.amazonaws.com/0/92480/b41d5a55-4d75-a56c-d786-3f33e0bcc225.jpeg)

## Plug.Debuggerで出来ます
```elixir:lib/hoge_web/endpoint.ex

defmodule HogeWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :hoge

  if Mix.env == :dev do
    use Plug.Debugger,
      otp_app: :hoge,
      style: [primary: "#eb9dc7", accent: "#eb9dc7", logo: "data:image/png;base64,..."]
  end
  # ...
```
`:style`以外にもこの画面に入ってきた値を受け取ってごにょごにょする関数を渡せたりします(`:banner`)

詳しくはこちらを https://hexdocs.pm/plug/Plug.Debugger.html

# まとめ
Plug.Debugger、公式doc以外に記事が無かった...
2018はPhoenixやcowboyで業務を行なってきましたが、2019もお世話になります🙇‍♂️

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">Phoenixのデバッグ画面を名取さな仕様にして遊んでる(Plug.Debuggerにstyleオプション渡した) <a href="https://t.co/y6HUkkCU0w">pic.twitter.com/y6HUkkCU0w</a></p>&mdash; nagimaru (@ngmr_mo) <a href="https://twitter.com/ngmr_mo/status/1074232561528856576?ref_src=twsrc%5Etfw">December 16, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Reactで超簡単な画像ビューアを作る - FileReader

ReactでFileReaderを使った、超簡単な画像ビューアを作ってみました。


```
npx create-react-app image-upload
cd image-upload
rm -rf src
```

新たに以下のファイルをsrcに置きます。


```react:src/index.js
import React, { Component } from 'react'
import { render } from 'react-dom'

class App extends Component {
  state = { 
    file: "", 
    imagePreviewUrl: ""
  }

  handleFileChange = (e) => {
    e.preventDefault()
    let reader = new FileReader()
    let file = e.target.files[0]
    reader.onloadend = () => {
      this.setState({
        file: file,
        imagePreviewUrl: reader.result
      }); 
    }   
    reader.readAsDataURL(file)
  }

  render() {
    console.log("imagePreviewUrl=" + this.state.imagePreviewUrl);
    return (
      <div>
        <input type="file" onChange={this.handleFileChange.bind(this)}/>
        <img src={this.state.imagePreviewUrl} />
      </div>
    )   
  }
}

render(<App />, document.getElementById('root')) 
```


ここでは「input type="file"」でアップロードした画像ファイルを **[FileReader - MDN](https://developer.mozilla.org/ja/docs/Web/API/FileReader)**というライブラリを使って、URLに変更しています。

```:FileReader
FileReader()
新しく作成された FileReader を返します。

FileReader.onloadend
loadend イベントのハンドラです。読込が（成功・失敗によらず）終了したときにイベントが発生します。

FileReader.readAsDataURL()
指定された Blob オブジェクトを読み込みます。
終了後の result プロパティには、ファイルのデータを示す「data: URL」が格納されます。
```


「**data: URL**」とは次のようなものです。つまり、data: スキームが先頭についた URL であるデータ URL を使うと、コンテンツ制作者は小さなファイルをインラインで文書に埋め込むことができます。詳細は「[**データ URL** - MDN](https://developer.mozilla.org/ja/docs/data_URIs)」を参照してください。




以下が初期画面です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61915/a4700083-cf2d-f98f-142e-a923f629926b.png)


犬の写真を選択してみました。ちゃんと表示できますね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/61915/838bf20a-e8df-89a4-9a6b-96d50d57be2e.png)



今回は以上です。
SikuliX　if exists( )を活用

if exists( )の活用


Find( )やClick( )などでFindFailed が発生し場合、Sikuliの実行が停止してしまいます。
処理を止めないためにif exists( )を利用します。

　exists関数は対象の画像発見されるまで待機します。

　exists([画像] ,タイムアウト値（秒）)：タイムアウト値は省略可能です。その場合は3秒となります。

１．以下のように記載し、対象のオブジェクトが発見できなかった場合にFindFailedで停止してしまいます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/325544/9e0ca715-d8b2-63f6-62c3-294c7c6cdf93.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/325544/1a1b0440-394d-3a76-3378-c9de0b38c808.png)

2．ｉf exists( )を利用することにより回避が可能となります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/325544/65764a06-b891-45cf-6cb8-9e1c26393cd3.png)
AOJ day 24: Modeling Chart.js spec building with rows

# English

While we've previously talked about ways to model JS charting library specs by using Row.Union, another interesting viewpoint to look from instead is how to allow for building an arbitrary spec just based on restricting what properties can be set based on what kind of chart we are building.

## "Using Rows and RowToList to model Chart.js spec building"

In this article, I talked about how we might model spec-building for Chart.js, by using a row type to specify which functions for builder components are valid for which types of charts:

<https://qiita.com/kimagure/items/fd05ad13ee8def0fb4ed>

The problem that this article mainly focused on was that we needed to get the intersection of two row types when composing chart builders:

```hs
newtype ChartBuilder
  (appliesTo :: # Type)
  (input :: # Type)
  (output :: # Type)
  = ChartBuilder (Builder (Record input) (Record output))
```

So to compose two of these chart builders together, we need to make sure that the new chart builder that we output has a `appliesTo` parameter that is valid. So given the composition of `( a :: _ , b :: _ )` and `( a :: _ )`, we need to produce the output `( a :: _ )`.

While it would be convenient if we could have multiple constraints solved simultaneously to allow us to express a system of Union constraints, we do need to actually implement this in terms of RowToList as only one constraint can be fully determined at a time. I wrote about this problem more in the follow-up article, "Making Diffs of differently-typed Records in PureScript", so I hope you'll read through it sometime:

<https://qiita.com/kimagure/items/ca229cb4ba76db0c24a8>

---

# Japanese

以前に、Row.Unionを使用してJSのグラフライブラリ仕様をモデル化する方法について説明しましたが、目的とするグラフでどのような種類のプロパティを設定できるかを制限し、これに基づいて任意の仕様を構築する方法があります。

## "row型とRowToListを使ってChart.js仕様をモデル化する"

以下の記事では、row型を使用してビルダーコンポーネントの関数がどの型のグラフに対して有効かを指定することによって、Chart.jsの仕様作成をモデル化する方法について説明しました。

<https://qiita.com/kimagure/items/fd05ad13ee8def0fb4ed>

この記事で注目した問題は、`ChartBuilder`を作成するときに2つのrow型の合成を取得する必要がある点です。

```hs
newtype ChartBuilder
  (appliesTo :: # Type)
  (input :: # Type)
  (output :: # Type)
  = ChartBuilder (Builder (Record input) (Record output))
```

これら`ChartBuilder`の2つを一緒にするには、出力する新しい`ChartBuilder`に有効な `appliesTo`パラメータが有効であるかを確認する必要があります。そのため、 `( a :: _ , b :: _ )`と `( a :: _ )`の構成を考えると、出力`( a :: _ )`を生成する必要があります。

Union制約のシステムを表現するために複数の制約を同時に解決できるのであれば便利ですが、一度に1つの制約しか完全に決定できないため、RowToListに関して実装する必要があります。この問題については、"PureScriptで異なる型のレコードの差分を取る"という記事で詳しく書かれていますので、時間があれば読んでください。

<https://qiita.com/kimagure/items/ca229cb4ba76db0c24a8>

---

Thanks to @noolbar for the Japanese translation!
SikuliX　Region（領域）を利用してオブジェクトの選択

Region（領域）
   複数の同一オブジェクトが存在し、特定のオブジェクトを選択させたい場合に有効です。
　　（オブジェクトイメージが変わらないものが複数存在した場合に有効）
 

１．以下のような、同一イメージのボタンを上から順にクリックするする場合

![image.png](https://qiita-image-store.s3.amazonaws.com/0/325544/2f0a266d-60ab-8efa-7686-3cfa02414342.png)

２．Region（領域）を指定することにより実行可能です。

　　　　Regionの指定は、上段のRegionボタンをクリックし、FindやClickに利用したい範囲を指定します。

　　　　以下、サンプル
![image.png](https://qiita-image-store.s3.amazonaws.com/0/325544/cb1db516-eb6e-c184-f192-7fb61fc56ecd.png)

３．実行結果

![o1339052313817264336.gif](https://qiita-image-store.s3.amazonaws.com/0/325544/2c9961b6-3d6f-0658-399b-cd6ba60f3b89.gif)
チャットコミュニケーションの非同期性を最大限活かすためのおすすめslack設定

# 設定の目的

* 出社中7,8割以上の時間PCに張り付いている
* 口頭会話より慣れるとslackでのやり取りのほうが楽なので、slack利用を促進したい
* 自分に関係した話、もしくは注視しているチャンネルにはすぐ反応したい、一方で比較的関連度の低いチャンネルは自分と関係のない発言があってもスルーしたい

# 設定

## 通常出勤で絶対会社にいない時間はおやすみモードに設定する

設定方法: [おやすみモードによる通知の一時停止 – Slack](https://get.slack.help/hc/ja/articles/214908388-%E3%81%8A%E3%82%84%E3%81%99%E3%81%BF%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AB%E3%82%88%E3%82%8B%E9%80%9A%E7%9F%A5%E3%81%AE%E4%B8%80%E6%99%82%E5%81%9C%E6%AD%A2)

話しかけようとした人へ、返事がすぐ返ってこない可能性に来づけるよう設定する。

## (おやすみモードのとき以外は)通知設定で必ず発言には気づくようにする

[設定画面](https://triplew.slack.com/account/notifications)

目の前でPCを開いているにも関わらずslack上で自分宛てに送ったメッセージに何十分も気づかないと相手は直接話しかける必要に駆られる。
こんなことが何度も続くと相手のチャットコミュニケーションへの信頼性が薄れ、slackが有効活用されなくなる。
PCを開いている限りは自分へのメンション、自分が注視しているチャンネル上の発言は必ずチェックできるようにすること。

## 関連度の低いチャンネルはきちんとミュートする

設定方法: [重要事項を見逃さないために – Slack](https://get.slack.help/hc/ja/articles/217626558-%E9%87%8D%E8%A6%81%E4%BA%8B%E9%A0%85%E3%82%92%E8%A6%8B%E9%80%83%E3%81%95%E3%81%AA%E3%81%84%E3%81%9F%E3%82%81%E3%81%AB#%E9%80%9A%E7%9F%A5%E3%82%92%E6%B4%BB%E7%94%A8%E3%81%99%E3%82%8B)

業務上、とりあえず入ったが自分との関連性が低いようなチャンネルは設定からミュート状態にする。

チャンネル内のコミュニケーションの活発度にもよるが、非ミュート状態のチャンネルはたかだか10個程度にしておいたほうが良い。

## 自分と関連性が高いチャンネルはスターをつける

設定方法: [チャンネル・メッセージ・ファイルにスターを付ける – Slack](https://get.slack.help/hc/ja/articles/201331016--%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB-%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E3%82%B9%E3%82%BF%E3%83%BC%E3%82%92%E4%BB%98%E3%81%91%E3%82%8B)

自分が属するチームのチャンネルやアラートチャンネルなどはスターを付けてチャンネルの表示順の上方は持ってくる。
これでより未読に気づきやすくなる。
一方で#generalや#randomのようなチェックしているが自分との関連度が低いチャンネルはそのままにしておく(こちらは即応できなくても大抵問題ないため)

# 上記設定をふまえたslackとの付き合い方

1. 未読状態は一切放置しない
2. 昼休みや外出中、MTG中などは無理にslackで反応しようとせず、帰社後やMTG終了後に**確実にこちらから対応するようにする**
3. 返事や対処方法に困るものは、対応目安(MTG後に確認します、明日中目安で対応します, ...)を書いた上でメッセージの「・・・」ボタンから「あとでリマインドする」を使って一定時間後通知してくれるよう設定して絶対に忘れないようにする

上記、これをすることにより自分へ話しかけてきた人は次のように判断できる。

1. 今コミュニケーション取れる状態ならslackで話しかければ必ずリアクションがある
2. slackで話しかけてリアクションがなくても、相手はslack上の会話に気づけば必ず向こうからアクションしてくれる
    * → ということはこの件は一旦忘れて別の仕事ができる(ボールをこちらに預けることができる)

これにより同じ場所に関係者全員がいなくても効率的に話を進めることができる。
SikuliX　Findallを利用する


Findall
   複数の同一オブジェクトが存在し、全てのオブジェクトに対して同一処理をさせたい場合に有効です。（全てのボタンをONからOFFに切り替えたい場合等）

   ※イメージの選択順は、Sikuliに依存するため順番にクリックさせたい場合などは注意が必要です。

 
１．以下のような、同一イメージのボタンを全てクリックするする場合

![image.png](https://qiita-image-store.s3.amazonaws.com/0/325544/2e9d376d-b010-b76c-be5d-24e119eea2f2.png)

２．Findallを指定することにより実行可能です。

　　　　以下、サンプル
![image.png](https://qiita-image-store.s3.amazonaws.com/0/325544/e9809e57-7e85-d107-d333-ad9d1e095ace.png)

　３．実行結果
![o1207051613817275444.gif](https://qiita-image-store.s3.amazonaws.com/0/325544/7eef6ae3-a040-fbf3-60aa-b06afd43c3de.gif)
AOJ day 23: Inferred error types

When we write sophisticated type-level code, usually the types should work such that they are fully determined in some way. This means that as long as we give the intermediate a value to correspond to, we'll have the inferred type available to us that we can use the PureScript IDE tooling to insert.

But how do we write a basic assertion that this inferred type should match something, instead of trying to manually verify that types infer to the result we expect?

## "Expecting Inferred Types (feat. Custom Type Errors)"

In this post, I talked about how we can use a simple two-parameter type class to assert that an inferred type should equal an expected type:

<https://qiita.com/kimagure/items/00c1ca57d6999904b595>

The main that this works with by having two instance, with the main instance being that the first and second parameters should be equal. Then an overlapping instance is defined using instance chain groups, which uses the Prim.TypeError module to make a custom Fail constraint, such that we can get an error like so:

```hs
test2 :: Unit
test2 =
  let
    -- this will error correctly:
    expectedP = Proxy :: Proxy String
    -- A custom type error occurred while solving type class constraints:
    --
    --   The expected (first) and actual (second) types did not match:
    --     String
    --     Unit
    --
    -- while applying a function expectInferred
    --   of type ExpectInferred t0 t1 => Proxy t0 -> t1 -> Unit
    --   to argument expectedP
    -- while inferring the type of expectInferred expectedP
    -- in value declaration test2
    simpleValue = simpleMethod (Proxy :: Proxy String)
  in
    expectInferred expectedP simpleValue
```

While many people complain about error messages in PureScript, we can see that the error message here is fairly straightforward if we slow down and read through its parts, telling us that the custom type error occured from the application of the `expectInferred` function. Really, PureScript errors are surprisingly good given the amount of type information we routinely work with, but you have to give it some patience.
obnizで自分だけの複数家電に対応したスマートリモコンをつくる

# はじめに
こんにちは、宇宙エンジニアのたくろーどんです。
秋のJavaScript祭にむけてつくった複数家電に対応した自分だけのスマートリモコンの話です．

# 経緯
年々，スマートフォンが増え，家電を買えば買う程リモコンが増えます
なので1つにまとめておけば，リモコンが見つからなくなってしまっても一安心…という動機です．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/212276/e122c8de-7cc0-1357-2ce0-c6c7e4fb2675.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/212276/fd76f3ee-0621-70d3-7856-bd51854dee08.png)

# 概要
概念図は下記のような感じです．
web上に専用のwebサイトをこしらえて，ログイン画面を付けて，直感的に操作できるようにします．
マイコンにはobnizを使っています．
JavaScriptでプログラミングできるので，webとの相性が良さそうなので使ってみました．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/212276/13895bc1-b7c0-172a-730c-fa17453b1fee.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/212276/c94307ea-bdf2-e65a-ed37-9ba0c4321bce.png)

## ログイン画面
ログイン画面はfirebaseを使えばとても簡単につくれます． 

![image.png](https://qiita-image-store.s3.amazonaws.com/0/212276/0361cd9b-2967-cc8c-6406-7f1c02f14f3a.png)

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ログイン、ログアウト機能実装してみた <a href="https://t.co/BIlX4z3qZ0">pic.twitter.com/BIlX4z3qZ0</a></p>&mdash; たくろーどん@宇宙エンジニア (@takudooon) <a href="https://twitter.com/takudooon/status/1060436008209145856?ref_src=twsrc%5Etfw">2018年11月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## ジェスチャー操作
たたボタンを押すだけではつまらないので，Hammer.jsをつかってジェスチャー操作できるようにしました．
なので，照明をON/OFFするだけでなく，ジェスチャー操作を使うことでスワイプの方向によって正面を暗くしたり明るくしたりすることができます．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/212276/8651652e-b7e8-2d1a-c9b5-57d5a691075e.png)

プログラムはjQuery風に書けます．JavaScript初心者の私にでもわかりやすかった印象です．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/212276/511357d5-da75-2597-db2b-8d782fc36abc.png)

開発途中の動画ですが，こんな感じで家の照明を制御できました．

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">いい感じ。<br>hammer.jsつかって、家のライトをジェスチャー操作。 <a href="https://t.co/FCZqf1tS8z">pic.twitter.com/FCZqf1tS8z</a></p>&mdash; たくろーどん@宇宙エンジニア (@takudooon) <a href="https://twitter.com/takudooon/status/1060283175933435905?ref_src=twsrc%5Etfw">2018年11月7日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# まとめ
プログラムは[github](https://github.com/minwinmin/Smart-Remote-Controller)にあげました．
卒論提出したら力尽きました．
AOJ day 22: Naporitan, reflecting a record of proxies

To group a bunch of proxies together either for convenience or for RowToList-directed type-level verification, you might choose to put them in a record. However, this usually leaves us in a position where we then need to go through and write out the value of our proxy literally, leading to a load of repetition and pain, where we need to make sure we have actually declared all of the fields in our record of proxy types below.

If PureScript has taught us anything, it's that if we have static knowledge about something, we should be able to derive its value.

## "Reflecting a record of proxies and keys of row types"

In this post, I wrote about how we can once again use RowToList with the combination of Record.Builder to reflect a record of proxies into its value:

<https://qiita.com/kimagure/items/b08175d22f9950ba3dfb>

Just like that, we don't need to write any error-prone boilerplate, since we can use the compiler to derive the value:

```hs
proxies ::
  { apple :: Proxy Int
  , banana :: Proxy String
  }
proxies = N.reflectRecordProxy
```

I hope even if this example seems a bit silly, this really gives you some ideas on how powerful languages really can derive values for you from the types, and how this is really incredibly useful when you make a conscious choice of what you'd like to get out of your system. Otherwise, there would be a much smaller difference between PureScript and other languages.
React HooksでTutorialをやってみる（TypeScript）

この記事は[React.js Advent Calendar 2018](https://qiita.com/advent-calendar/2018/react)の15日目の記事です。

。。。完全に忘れていましたorz

という事で、[公式のチュートリアル](https://reactjs.org/tutorial/tutorial.html)を[React Hooks](https://reactjs.org/docs/hooks-overview.html)でやってみました。

コードは[こちら](https://github.com/f-a24/react-tutorial-hooks)

# 環境構築
create-react-app使います。

```
yarn create react-app react-tutorial-hooks --scripts-version=react-scripts-ts
cd react-tutorial-hooks
yarn add react@16.7.0-alpha.2 react-dom@16.7.0-alpha.2
```

# Hooks使いどこ
Classを全てFunctionに変えて、useStateを使います。

```js
/* before */
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      history: [
        {
          squares: Array(9).fill(null)
        }
      ],
      stepNumber: 0,
      xIsNext: true
    };
  }
/* after */
const App = () => {
  const [history, setHistory] = React.useState([
    {
      squares: Array(9).fill(null)
    }
  ]);
  const [stepNumber, setStepNumber] = React.useState(0);
  const [xIsNext, setXIsNext] = React.useState(true);
```

チュートリアルではこのぐらいしかなかったですね。。。

# まとめ
普段、recompose使っているので特に違和感はなく「あぁ、withStateとかwithHandlersか」的な感覚でした。
今回はuseStateしか使っていませんが、他にも色々あるので調べていこうかなと思います。
Chainerのログをログコレクターと連携させる

# 概要

Chainer のログは本体に同梱されている LogReport extention を使うと JSON 形式で出力されますが、Fluentd などのログコレクターと連携させる場合は JSONL 形式で出力されたほうが便利です。今回は Chainer のログを JSONL 形式で出力する extention を作成しました。

# 使い方

- インストール

```shell
$ pip install chainer-jsonl-report
```

- 学習コード

```python3
from chainer_jsonl_report import JsonlReport
...略...
trainer.extend(JsonlReport())
trainer.extend(extensions.PrintReport(
    ['epoch', 'iteration', 'main/loss', 'validation/main/loss',
     'main/accuracy', 'validation/main/accuracy', 'elapsed_time'],
    log_report='JsonlReport',
))
```
LogReport の代わりに JsonlReport を extend し、PrintReport の引数に `log_report='JsonlReport'` を指定すれば完了です。全体のコードは[こちら](https://github.com/nel215/chainer-jsonl-report/blob/master/example/train.py)にあります。実行すると以下の様な1行1JSONなログが出力されます。

```
{"main/loss": 0.3365242703319358, "main/accuracy": 0.9054337686567164, "validation/main/loss": 0.15602408988472027, "validation/main/accuracy": 0.9532238924050633, "epoch": 1, "iteration": 469, "elapsed_time": 3.0503302490105852}
{"main/loss": 0.13408539906493636, "main/accuracy": 0.9597381396588486, "validation/main/loss": 0.11228864842766448, "validation/main/accuracy": 0.9659810126582279, "epoch": 2, "iteration": 938, "elapsed_time": 6.065310915000737}
{"main/loss": 0.09253230937587809, "main/accuracy": 0.9720815565031983, "validation/main/loss": 0.08980113636890921, "validation/main/accuracy": 0.9706289556962026, "epoch": 3, "iteration": 1407, "elapsed_time": 9.113151438999921}
{"main/loss": 0.06868528947234154, "main/accuracy": 0.9787660256410257, "validation/main/loss": 0.08547733464761625, "validation/main/accuracy": 0.9716178797468354, "epoch": 4, "iteration": 1875, "elapsed_time": 12.126692335004918}
{"main/loss": 0.054074254724929834, "main/accuracy": 0.9828924573560768, "validation/main/loss": 0.07506902210555877, "validation/main/accuracy": 0.9773536392405063, "epoch": 5, "iteration": 2344, "elapsed_time": 15.149620360985864}
...
```

# 利用例

MNIST の学習結果を Fluentd + Elasticsearch + Kibana で可視化してみました。全体のコードは[こちら](https://github.com/nel215/chainer-jsonl-report/tree/master/example/efk)にあります。

- 実行方法
docker-compose でまとめているので `docker-compose up` した後にブラウザで実行しているマシンの6501番ポートにアクセスするだけです。

- Discover
![discover.png](https://qiita-image-store.s3.amazonaws.com/0/15369/f72ae408-bf9a-c628-7c4d-7028bde0fa47.png)
- Visualize
![visualize.png](https://qiita-image-store.s3.amazonaws.com/0/15369/0068d7ca-4067-3d04-479b-59ada6f337e6.png)

※ちなみに可視化に関しては学習に関する操作(スナップショットや学習停止など)も組み込まれている [ChainerUI](https://github.com/chainer/chainerui) があるのでそちらを使ったほうが良いと思います。



# まとめ

- Trainer のログを JSONL 形式で出力する extension を作成しました
- 利用例として、ログコレクターの Fluentd と連携させて elasticsearch にログを保存し、kibanaで可視化しました
Glueの使い方的な㉛(GlueやAthenaで見えるテーブルを制限する)

# Glue リソースポリシーでアクセスコントロール

ユーザーAはGlueデータカタログのテーブル１が閲覧操作できるが、ユーザーBはGlueデータカタログのテーブル1を閲覧操作できないなどを実現する。

https://aws.amazon.com/jp/about-aws/whats-new/2018/10/aws-glue-now-supports-resource-based-policies-and-resource-level-permissions-and-for-the-AWS-Glue-Data-Catalog/

# 試す

管理者ユーザーは全部操作でき、se2_user31という名前のユーザーは閲覧操作できるテーブルに制限が掛かってることを確認

## 管理者ユーザーから確認

Glueデータカタログのデータベースが全部見えます

![スクリーンショット 0030-12-16 17.33.30.png](https://qiita-image-store.s3.amazonaws.com/0/27932/4a785487-50ef-a14a-1d88-88b460c7824e.png)

Glueデータカタログのテーブルが全部見えます

![スクリーンショット 0030-12-16 17.33.56.png](https://qiita-image-store.s3.amazonaws.com/0/27932/946d4066-c2fd-037e-4d4b-31783c61e2ba.png)

## 特定ユーザーに閲覧操作できるテーブルを限定します

ユーザー名：se2_user31
対象データベース：se2
対象テーブル：se2の配下すべて

Glueの画面から、[設定]をクリックし、"アクセス権限"の箇所にポリシーを書きます。

<img width="846" alt="スクリーンショット 0030-12-16 15.19.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/27932/fa3e9584-4b38-2014-1831-47419ab3fe47.png">

ポリシーは以下のように、「se2_user31というユーザーが、データカタログのデータベースse2とデータカタログのテーブルのse2配下全部に対して閲覧操作可能」という内容です。

※se2_user31ユーザーのIAMポリシーにはGlueの設定はなにも入れない

```json:
{
  "Version" : "2012-10-17",
  "Statement" : [ {
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "arn:aws:iam::xxxxxxxxxxxx:user/se2_user31"
    },
    "Action" : "glue:*",
    "Resource" : [ "arn:aws:glue:ap-northeast-1:xxxxxxxxxxxx:catalog", "arn:aws:glue:ap-northeast-1:xxxxxxxxxxxx:database/se2", "arn:aws:glue:ap-northeast-1:xxxxxxxxxxxx:table/se2/*" ]
  } ]
}
```

## 動作確認

se2_user31ユーザーでログインし、データカタログのデータベースを見る。
se2だけ表示される

![スクリーンショット 0030-12-16 17.42.06.png](https://qiita-image-store.s3.amazonaws.com/0/27932/0dfa13fb-7cb2-d04c-17ab-e4c9f474d74d.png)

データカタログのテーブルを見る。
なにも見えない

![スクリーンショット 0030-12-16 17.42.19.png](https://qiita-image-store.s3.amazonaws.com/0/27932/62d21be6-884d-342a-154e-34972e559ef4.png)

検索窓で「データベース：se2」でフィルタリングすると表示される

![スクリーンショット 0030-12-16 17.42.32.png](https://qiita-image-store.s3.amazonaws.com/0/27932/21fd2955-6bea-78b3-a192-b08c0119ef2a.png)

Athenaからも確認。同様にse2のデータベースとテーブルだけが表示される

![スクリーンショット 0030-12-16 17.49.01.png](https://qiita-image-store.s3.amazonaws.com/0/27932/6d83b0b0-6a57-810a-e1c1-c0251d9f60f2.png)

## 注意

この機能はメタデータへの権限制御なのでS3は関係ない。S3への権限があればS3にある実データを読み書き削除を行えてしまう。必要なら実データが入っているS3への権限制御も付与を行う

## その他

アクセスコントロール用の AWS Glue リソースポリシー
https://docs.aws.amazon.com/ja_jp/glue/latest/dg/glue-resource-policies.html

AWS Glue データカタログ のデータベースとテーブルへのきめ細かなアクセス
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/fine-grained-access-to-glue-resources.html

Glueの使い方まとめ
https://qiita.com/pioho07/items/32f76a16cbf49f9f712f
Goの正規表現の文字置換のベンチマーク比較

Golangで正規表現を使おうとなると、何も考えないとregexpなどを使ってしまいたくなりますが、他の方の記事(参考文献に記載)にもあるように速度がかなり遅くなってしまいます。

そこで、今回はGolangの正規表現のパターンとその速度を検証してみたいと思います。

### 比較の前提
まず用いるアルゴリズムですが、regexpによる正規表現、strings.Replacerによる置換を用います。また呼び出し方もregexpとstrings.Replacerはそれぞれ正規表現の宣言(それぞれMustCompileとNewReplacer)をループごとに呼び出すかという話があるので、

* regexpによる正規表現(MustCompile中/外)
* strings.Replacerによる正規表現(NewReplacer中/外)

の計5パターンを試してみたいと思います。

比較の方法については簡単な正規表現を用います。用途によっても色々あると思うのですが、今回は短文ですが以下の文章を使います。イメージとしてはメールの文章の個人名を正規表現で伏せるという用途を考えます。

```
田中さん、お元気ですか。今度の火曜日に鈴木さんと打ち合わせがあるのですがご都合いかがでしょうか。
```
これを

```
XXさん、お元気ですか。今度の火曜日にXXさんと打ち合わせがあるのですがご都合いかがでしょうか。
```

### 比較結果

```go

package main

import (
	"regexp"
	"strings"
	"testing"
)

// Compile抜きReplacer
func BenchmarkReplace(b *testing.B) {
	str := "田中さん、お元気ですか。今度の火曜日に鈴木さんと打ち合わせがあるのですがご都合いかがでしょうか。"
	rep := strings.NewReplacer("田中", "XX", "鈴木", "XX")
	for n := 0; n < b.N; n++ {
		_ = rep.Replace(str)
	}
}

// Compile込みReplacer
func BenchmarkReplaceIn(b *testing.B) {
	str := "田中さん、お元気ですか。今度の火曜日に鈴木さんと打ち合わせがあるのですがご都合いかがでしょうか。"
	for n := 0; n < b.N; n++ {
		rep := strings.NewReplacer("田中", "XX", "鈴木", "XX")
		_ = rep.Replace(str)
	}
}

// コンパイル抜きReg
func BenchmarkReplacereg(b *testing.B) {
	str := "田中さん、お元気ですか。今度の火曜日に鈴木さんと打ち合わせがあるのですがご都合いかがでしょうか。"
	rep := regexp.MustCompile("田中|鈴木")
	for n := 0; n < b.N; n++ {
		_ = rep.ReplaceAllString(str, "")
	}
}

// コンパイル込みReg
func BenchmarkReplaceregIn(b *testing.B) {
	str := "田中さん、お元気ですか。今度の火曜日に鈴木さんと打ち合わせがあるのですがご都合いかがでしょうか。"
	for n := 0; n < b.N; n++ {
		rep := regexp.MustCompile("田中|鈴木")
		_ = rep.ReplaceAllString(str, "")
	}
}
```

```
BenchmarkReplace-4               5000000               397 ns/op             320 B/op          3 allocs/op
BenchmarkReplaceIn-4             1000000              1229 ns/op            1104 B/op         10 allocs/op
BenchmarkReplacereg-4             500000              2446 ns/op             368 B/op          4 allocs/op
BenchmarkReplaceregIn-4           200000              8887 ns/op           39392 B/op         31 allocs/op
```

だいたい、コンパイルがありとなしでns/ops換算でそれぞれReplacerは3.1倍・Regexpでは3.6倍の差が出ました。
また、ReplacerとRegexpでは7倍程度の差が出ました。

この辺はたしかにReplacerの方が早いという結果なのですが、Replacerの定義をfor文の中で行っている場合でもコンパイルを外においているRegexpより倍近く早い結果となりました。

### まとめ

今回はReplacerとRegexpの文字列置換についてまとめました。他の方々がやられているように、基本的にReplacerを使うのがベストとは思いますが、一方でstrings.NewReplacerの宣言部分をfor文の外に出すだけでも3倍近く早くなるという結果が得られました。

実際にコードに落とし込む際に、あまりに正規表現の宣言と利用部分がバラバラになっても管理しづらいケースがあるかもしれませんが、うまく使っていけばより早い速度向上に繋がるのかなと思ったりします。

### 参考文献

[Golangの正規表現がどれぐらいおそいのかをPythonと比較してみた話](https://qiita.com/tj8000rpm/items/b92d7617883639a3e714)

[regexpとの付き合い方 〜 Go言語標準の正規表現ライブラリのパフォーマンスとアルゴリズム〜](https://medium.com/eureka-engineering/regexp%E3%81%A8%E3%81%AE%E4%BB%98%E3%81%8D%E5%90%88%E3%81%84%E6%96%B9-go%E8%A8%80%E8%AA%9E%E6%A8%99%E6%BA%96%E3%81%AE%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9%E3%81%A8%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0-984b6cbeeb2b)

[Goの正規表現とReplacerを比較した](http://sgykfjsm.github.io/blog/2017/09/26/gofalsezheng-gui-biao-xian-toreplacerwobi-jiao-sita/)
DockerのLinuxコンテナ内で名前解決エラーに困っていたら、もくもく会参加者に助けられた話

[株式会社 SQUEEZE主催のPythonもくもく会](https://mokupy.connpass.com/event/111968/)参加時にDocker作業環境内からpipやapt-getが使えなくなるという事態に見舞われましたが、周りの参加者さんのおかげで無事解決できました。

本稿ではその時の状況と解決策を記事にしました。

# 環境
ホストマシン：Windows10 Home Edition
Docker : Docker ToolBox（バージョン情報未確認）
Docker内環境：Ubuntu 18.04.1 LTS

# 症状
apt-get, pip, git等、外部とのインターネット接続が必要なコマンドが機能しない。

実行例

```
# pip install update
>> Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x7f851e229518>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')':
```

ググったらproxyがどうのという記事が多く、最初はその線を疑っていました。
例）https://qiita.com/sch923/items/44ac748389dd68388467


しかし、参加者の方からは特別な設定なしで外部に接続できるからその線はなさそう、むしろDNS設定が怪しいとの指摘をいただきました。

確かに上記に`Temporary failure in name resolution`とあり、名前解決がうまくいっていないように見えます。

# 原因
アドバイスに従って、以下のコマンドを実行してみました。

```
# python -c "import socket; print(socket.gethostbyname('security.ubuntu.com'))"
>> Traceback (most recent call last):
>  File "<string>", line 1, in <module>
> socket.gaierror: [Errno -3] Temporary failure in name resolution
```

これにより、原因は名前解決がうまくいっていないことが明らかになりました。

なんでも、Docker ToolBoxが使っているVirtualBoxが指定するDNSキャッシュサーバー`10.0.2.3`には欠陥が存在するそうです。
https://qiita.com/matsuzan/items/aa0c8e2f52e191434e4f
https://fumiyas.github.io/vagrant/network.html

# 解決方法
Dockerの中から`/etc/resolv.conf`を書き換えました：

```:before
nameserver 10.0.2.3
```

```:after
#nameserver 10.0.2.3
nameserver 8.8.8.8
nameserver 8.8.4.4
```

これにより、再起動等することなく接続が回復し、`apt-get`, `pip`ともに今まで通り使えるようになりました！

# おわりに
Slackで丁寧にアドバイスしていただいた二人の参加者の方に感謝申し上げます。
【初心者向け】RailsでAPI開発 Part.2

# これは何？
[【初心者向け】RailsでAPI開発 Part.1
](https://qiita.com/jiggaman0412/items/49cf20ce8043e3be33b8)の続きです。

今回は認証編となります。

# 概要
## ▼ 仕組み
認証については、下記のように判定するものとする。

1. emailとpasswordが入力される。
2. 登録が完了したらトークンを発行してクライアントに返す。
3. クライアントは毎リクエスト、トークンをヘッダーに入れてリクエストを送る。

## ▼ 使用するもの
- has_secure_password
    - bcrypt（事前に追加しておいてください。）
- has_secure_token
    - ActionController::HttpAuthentication::Token
        - authenticate_with_http_token

# 手順
## ① UserModelを整える

```
- name:string
- email:string
- password_digest:string
- token:token
```

```ruby:addp/models/user.rb
before_save { self.email = self.email.downcase }
has_many :books
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
has_secure_token
```

上記のように設定することで、
バリデーションはもとより、Userが作成されると自動的に、
- セキュアなパスワードがDBに保存
- セキュアなトークンがDBに保存
されていく。

## ② UserControllerを整える
```ruby:app/controllers/v1/users_controller.rb
before_action :set_user, only: [:show]

def show
 render json: @user, adapter: :json
end

def create
 user = User.new(user_params)
 if user.save
  render json: user, adapter: :json, status: 201
 else
  render json: { error: user.errors }, status: 422
 end
end

private
def set_user
 @user = User.find(params[:id])
end

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

## ③ トークン認証
```ruby:app/controllers/application_controller.rb
include ActionController::HttpAuthentication::Token::ControllerMethods

rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

def authenticate
 authenticate_with_http_token do |token, options|
  @current_user = User.find_by(token: token)
  @current_user != nil ? true : render_unauthorized_request
 end
end

def render_unauthorized_request
 self.headers['WWW-Authenticate'] = 'Token realm="Application"'
 render json: { error: 'No Authentication' }, status: 401
end

def record_not_found
 render json: { error: 'Record not Found' }, status: 404
end
```

## ④ 認証が必要なページに設定
```ruby:app/controllers/v1/users_controller.rb
..
before_action :authenticate, except: [:create]
..
```

# まとめ
難易度の高いと思われていた認証も、
Railsの標準の機能でかなり簡単に実装できることがわかりました。

まずはサービスに登録させ、そのタイミングでトークンを発行してクライアントに送ってあげれば、
あとはヘッダーのトークン情報に合わせて認証しているかを判断しているだけです。
それをリクエスト毎に判断してあげるというシンプルな構造です。

次はPunditを使って認可周りを整えていきます。
ここまではサービスに登録しているかどうかだけの判断でしたが、
認可を作り込むことで、自分の情報だけは編集できるようにするなどのことができるようになります。
SlackでPublicチャンネルの発言を1箇所に集める方法

## はじめに
- 情報ジャンキーなのでチャンネルに投稿があると見ずにはいられません
- でもチャンネル数が多いと色んなチャンネルを行ったり来たりして大変
- なのでtimelineチャンネルを作り全てそこに集めてしまえば良いと思いBotkitでやってみました
- BotkitをSlackで使う方法は[こちらの記事](https://qiita.com/ishihamat/items/e90ec2e1faf80425a9fc)が参考になるかもしれません

## SlackBotの設定
- OAuth & Permissionsの設定に以下を追加します
  - users:read
  - chat:write:bot
  - chat:write:user(これはいらないかも？)
  - channels:history

- Event Subscriptionsの設定に以下を追加します
  - message.channels

## Botkitのコード
- .envファイルにtimelineチャンネルのIDを設定します
  - チャンネルIDを知るにはslackメッセージを右クリックしてコピーする方法が簡単だと思います
  - Cから始まるやつがチャンネルIDです

```bash:.env
timelineChannelId=Cxxxxxxxxx
```

- 3つのイベントに反応するようにします
  - ambient
  - direct_mention
  - mention
      - イベントについてはここに[こちら](https://botkit.ai/docs/readme-slack.html#event-list)詳しく書いてあります
- users.infoとchat.postMessageを使ってtimelineチャンネルに投稿します
  - users.infoの仕様は[ここ](https://api.slack.com/methods/users.info)に書いてあります
  - chat.postMessageの仕様は[ここ](https://api.slack.com/methods/chat.postMessage)に書いてあります

```Javascript:skills/timeline.js
module.exports = function(controller) {
  controller.on('ambient,direct_mention,mention', function(bot, message) {
      
      // ユーザトークンを使っているためボット作成者が参照できるプライベートチャンネルなどの発言も拾ってしまう
      // そのためchannel(パブリックチャンネル)でない場合は処理を終了する(そもそもPermissionsを与えなければ良いのですが念の為)
      const channel_type = message.event.channel_type;
      if(channel_type !== "channel"){ return }

      // 発言者の情報を取得する
      bot.api.users.info({user: message.event.user}, function(err, res){
          if(err) { console.log("err: ", err); return; }
          // timelineに発言するテキストを作成する（#チャンネル名 発言内容）
          const text = '<#' + message.event.channel + '> ' + message.event.text
          // チャンネル、テキスト、ユーザ名、ユーザアイコンを設定してtimelineチャンネルに投稿
          bot.api.chat.postMessage({ text: text, channel: process.env.timelineChannelId, as_user: false, username: res.user.profile.real_name, icon_url: res.user.profile.image_48}, function(err, res){
              if(err) { console.log("err: ", err); return; }
          });
      });
  });
}
```

## Slackイメージ

![Screenshot from 2018-12-16 17-18-26.png](https://qiita-image-store.s3.amazonaws.com/0/3507/c41fa6e7-c033-ce8c-0815-0ed1fe82beb5.png)

- 色んなPublicチャンネルの発言が集まって良い感じですね
- もはやPublicチャンネルはここだけ見ていれば良いかもしれません
- ちなみにこの日は弊社の忘年会で帰りにおいしいどら焼きが配られました
PHPerで最近、オブジェクト指向概念に触れたので勉強の計画を立ててみた

Advent Calendar YYPHP 12月16日を担当させていただきます。
毎日、内容が濃く、興味深いものが多く、それを見ているとなかなか、これらに続くqiitaをどうやってかけばいいかわからないということでとても悩んでおりました。

今年は、YYPHPさんに初参加させていただきたぶん4回くらい参加させていただきました。
参加される方のレベルの高さに恐縮すると同時に早く成長したいと思うようになりました。

これからソフトスキルズをフレームワークとしながらこれからの自分の勉強の予定を例にしながら読み手の方の参考になればいいなと思います。

僕自身はPHP2年そこそこでobject指向という未知な概念に最近触れたものです。

##### 1回のみ行う(ステップ１から６まで)

### ステップ1全体像をつかむ

これは、とんでもなく広いような気がします。
しかしながら、まとめたいと思います。

勉強したいものの全体

- PHPそのもの（型宣言やオブジェクト指向を実現する機能など）
- jsそのもの(アローで関数を省略するとか新しい書き方とか)
- 保守しやすい・読みやすいコードを書きたい（手段としてのオブジェクト指向）
- セキュリティ（安全なアプリケーションを作るため）
- インフラ（AWSなどでサーバを構築。Dockerも使えるようにする）
-　フレームワーク(laravel、Vue.js)

### ステップ2：スコープを決める

全部やりたいし、全部できるようになりたいですが、一旦スコープを決めます。

- オブジェクト指向の概念を学ぶ


### ステップ3：成功の基準を決める

オブジェクト指向の概念や実装方法を学び、Laravelの内部のソースなどを読み、良い書き方・悪い書き方を自分の中で考えながら読んで、自分の実装に反映できるようなる

### ステップ4：参考資料を見つける

ツイッター・qiita等で探す。
本や、web記事の情報のストックがあるのでまず、これを消化したいです。

### ステップ5：学習プランを作る

平日仕事が終わってから30分でもやりたいと思います。
週末も自分自身にアポを入れてやりたいです。

### ステップ6：リソースをフィルターにかける

全部、少し、試してみて参考になりそうなものを深掘りしてやっていきたいです。

以上、ステップ6までが1回だけ実行するステップです。

ここからは、繰り返すステップ ７から１０まで

### ステップ7：使い始められるようにする方法を学ぶ

interface/abstract/などを学んでLaravelのvender以下のソースの意味を読んで解釈できるようになりたいです。


### ステップ8：遊び回る

自分でオレオレフレームワークを生書きで作ってみたいです。

### ステップ9：役に立つことができるところまで学ぶ

Laravelで自分の作ったinterfaceコンポーネントを合体させてみる。

### ステップ10：教える
学んだことをQiitaに投稿したいです。
自分のlogになるし、他のひとの役にたったらうれしいです。


参考サイト
SOFT SKILLS ソフトスキルズで学び方を学ぶ
https://qiita.com/homhom99/items/89c875ffa2f289377e2c


最後までお読みいただきありがとうございました。
WHR-HP-GNを純正ファームで焼き直す

#はじめに
バッファロー製Wifiルーター WHR-HP-GN（以下エアステーション）にOpenwrtを書き込んで使っていたのですが、諸事情により純正ファームに戻す必要が出てきました。
しかし、導入手順を読み飛ばしてWebインターフェイスからフラッシュしたのでtftpの使い方がイマイチわからない...
試行錯誤の末にうまくいったのでまとめました。
私が試したのはWHR-HP-GNですが、同じシリーズのWHR-HP-G300Nなどでもいけると思います。

##ファームウェアの準備
バッファローのサイトから対応する機種のファームウェアをダウンロードして展開しておきます。
http://buffalo.jp/download/driver/index_wireless.html

##tftpの用意とipアドレスの設定
「プログラムと機能」-> 「windowsの機能の有効化または無効化」-> 「TFTPクライアント」にチェックを入れます。

ipアドレスを 192.168.11.2、ネットマスクを255.255.255.0に設定します。

エアステーションとPCを一対一で接続した状態で
`netsh interface ip show config`
を実行して有線接続のインターフェイス名を特定します。

##書き込みの準備
arpテーブルの設定のためにエアステーションのMACアドレスを確認します。
初期設定のSSIDがそのままMACアドレスになります。
書き込みはタイミングが重要なので、一発でコマンドを流し込めるbatファイルの作成をお勧めします。

```fw_write.bat
netsh interface ipv4 set neighbors "インターフェイス名" 192.168.11.1 "エアステーションのMACアドレス"
tftp -i 192.168.11.1 put ファームウェアのパス
```
MACアドレスはコロンではなくハイフン区切りで指定してください。
例：00-24-aa-bb-dd-ee

##書き込み
いよいよ書き込みです。
おそらく一回では成功しないので根気よくやってください。

####手順
エアステーションのLAN側とPCをつなぎます。
エアステーションの電源を入れ、繋いでいるポートのLEDだけが点灯したらすかさずbatを実行します。
**注意：このとき、管理者として実行してください。**

ファームウェアの転送に成功したら、その旨がコンソールに出力されます。
DiagランプとPowerランプが点灯します。Diagランプが消灯するまでそのままそっとしておいてください。

転送に失敗した場合は、電源を切り、タイミングを数秒ずらして再トライしてください。
転送の受付時間は4秒なのでかなりシビアです。
コンテナGo

#Goをコンテナ化する
[MySQLでGo](https://qiita.com/uguisu/items/96b438fb05f244a40a68)の続きです。
ローカルで動かしていたGOをコンテナ化し、ローカルMySQLに接続してテーブル情報を取得したいと思います。
完成したコードは[GitHub](https://github.com/uguisuhohokekyo/webapp_gogo/tree/containerized)に配置してあります。

#やってみた
##dockerのバージョン

```
$ docker -v
Docker version 18.09.0, build 4d60db4
```


##DockerHubからgolangイメージをpull

dockerイメージをpullします。バージョンを指定しない場合は、latestがインストールされます。
[GolangのOFFICIAL REPOSITORY](https://hub.docker.com/_/golang/)

```
$ docker pull golang
$ docker pull golang:1.8
```

##Dockerfile作成

Dockerイメージを作成するためのファイルです。

```Dockerfile
# 自分のイメージの元として現在の公式レポジトリを使用
FROM golang:1.8

# 作者
MAINTAINER uguisuhohokekyo

# 環境変数の設定
# ENV aaa=bbb

# ワーキングディレクトリ
# WORKDIR

# ローカルからコピー
COPY /src /go/src/
COPY /config /go/config/

# 特定のネットワーク・ポートをコンテナが実行時にリッスンすることを Docker に伝えます
EXPOSE 8080

#パッケージインストール
RUN go get -u github.com/go-sql-driver/mysql

# コンテナ内で実行するコマンド
CMD ["go", "run", "/go/src/mysql.go"]
```

##.dockerignore作成
特定のファイルとディレクトリをCLIの処理から除外から除外します。

```.dockerignore
# 特定のファイルとディレクトリはCLIの処理から除外
*/tmp*
.git*
!README.md
```

##設定ファイル

前回までは設定をコードにベタがきしていました。[12factor](https://12factor.net/ja/config)にそって設定をコードから分離しようと思います。

jsonの設定ファイルを作成し、そっちに環境依存の設定(今回でいうとMYSQLの接続情報)を書きます。


```config/mysql-config.json 
{
    "//": "docker用",
    "host": "host.docker.internal",
    "user": "uguisu",
    "pass": "sqlserver",
    "port": "3306",
    "dbname": "goods"
}
```

"host.docker.internal"はローカル環境DNS名で、指定するとDocker環境からローカル環境に接続できます。
[Networking features in Docker for Mac](https://docs.docker.com/docker-for-mac/networking/)


##mysql.go

設定ファイルを読み込むように修正します。中身は[GitHub](https://github.com/uguisuhohokekyo/webapp_gogo/tree/containerized)みていただければと思います。


#イメージをビルド
それではイメージをビルドします。-tでイメージ名をつけています。

```
$ ls
Dockerfile	README.md	config		src
$ docker build -t golang-mysql .
$ docker images | grep golang-mysql
golang-mysql            latest              5d56e672d35d        10 minutes ago      715MB
```

#docker run
イメージからプロセスを生成します。

```
 docker run --rm -d -p 8080:8080 -it golang-mysql
```

オプションの抜粋

```
-i, --interactive                    Keep STDIN open even if not attached
-p, --publish list                   Publish a container's port(s) to the host
-d, --detach                         Run container in background and print container ID
-t, --tty                            Allocate a pseudo-TTY
--rm                             Automatically remove the container when it exits
```

# 確認
MySQLが起動していることを確認して、
http://localhost:8080/getfruit

以下のように表示されれば成功です。
<img width="330" alt="スクリーンショット 2018-12-16 17.09.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/231906/85a427de-edca-9ba2-4f0a-0a3dd46cd4d0.png">

# お掃除

```
docker stop $(docker ps -q)
```
で停止できます。

#参考

[golangでdockerをはじめる ~ goのwebサーバーをdockerでたててみた ~](https://qiita.com/vankobe/items/f4c09e8e4b580651b568)
[Dockerfile のベストプラクティス](http://docs.docker.jp/engine/articles/dockerfile_best-practice.html)
Pandas to_csv関数でCSVファイルにダブルクォーテーションを2個続けて出力する方法

# PythonでCSVファイルを出力する際に、ダブルクォーテーションを2個続けて出力するのにハマったのでメモ。

## 動作確認環境
OS Windows8.1
Python 3.6.4
pandas 0.22.0

## 対応方法
to_csv関数のquoting引数に csv.QUOTE_NONNUMERIC を指定。

## サンプルコード
import pandas as pd
import csv
import numpy

\# データフレームにデータをセット
df = pd.DataFrame([{'data1': 'ABC', 'data2': 100, 'data3': 3.14, 'data4': numpy.nan, 'data5': '', 'data6': ""}])

\# CSVファイルを出力
df.to_csv('output.csv', index=False, encoding='utf-8', quoting=csv.QUOTE_NONNUMERIC)

## CSVファイル出力結果
"data1","data2","data3","data4","data5","data6"
"ABC",100,3.14,"","",""

## 【参考】quoting引数によるCSVファイル出力結果の違い
### quoting=csv.QUOTE_MINIMAL　←デフォルト値
＜CSVファイル出力結果＞
data1,data2,data3,data4,data5,data6
ABC,100,3.14,,,

### quoting=csv.QUOTE_NONE
＜CSVファイル出力結果＞
data1,data2,data3,data4,data5,data6
ABC,100,3.14,,,

### quoting=csv.QUOTE_ALL
＜CSVファイル出力結果＞
"data1","data2","data3","data4","data5","data6"
"ABC","100","3.14","","",""

### quoting=csv.QUOTE_NONNUMERIC　←本文から再掲
＜CSVファイル出力結果＞
"data1","data2","data3","data4","data5","data6"
"ABC",100,3.14,"","",""