OmniAICreator/Qiita-1.07M huggingface dataset:
社内にSlack上での分報を導入しないかと提案してみた

社内に分報を導入したくて、QiitaTeamに記事あげた時のものです。
こちらの記事参考に作りました。（かなり参照してる）
ありがとうございます。

- [Slackで簡単に「日報」ならぬ「分報」をチームで実現する3ステップ 〜 Problemが10分で解決するチャットを作ろう](http://c16e.com/1511101558/)
- [Slack分報についての質問と回答：僕のチームではどのように分報しているか？](http://c16e.com/1511171901/)

社内に分報導入したいという方、丸パクリで使ってもらって大丈夫です。以下です。


-----------

みなさまこんばんは。
田本です。

最近（というかけっこう前から）感じていた課題を「解決できるのでは！」
と思った運用方法を見つけましたので、
ミカタチームでも導入しませんか？！という話です。

# 最近（というかけっこう前から）感じている課題
1.　要件などの情報が各担当者に限定される
当初３人くらいで開発進めてた時には全く思いませんでしたが、メンバーが増える度に感じてます。
「えっと、これどうなってるんだっけ。。。？」とか
並列でプロジェクトが進んでいる時に逐一確認するのに時間がかかる。  



2.　今その人がなにやってるかわからない
相手の状況が把握しにくいですね。

3.　今どのような状況かわからないのでダイレクトチャットで聞く時にちょっと遠慮してしまう
2の延長ですね。
特に、ちょっとしたことだけど回答に時間がかかるという内容を聞く時に遠慮してしまいます（自分だけ？）


# 解決案
以前共有しましたが、この分報を導入するといいことだらけな気がしています。
読んでください（強制感）
[Slackで簡単に「日報」ならぬ「分報」をチームで実現する3ステップ 〜 Problemが10分で解決するチャットを作ろう](http://c16e.com/1511101558/)


# 導入・運用方法
###導入
1.　チームメンバ全員分のチャンネルをSlackに作る。チャンネル名は#times_{ユーザ名}。
2.　全員のチャンネルを作り、Slackで共有する。
3.　とにかくなんでも書いていいというルールを作り、周知する。

>この分報チャンネルは、社内Twitter的なものです。
>「今やってること」や「今困ってること」から、猫写真・昼飯、何でもありなので、どんどんつぶやいてください。
>お互いのチャンネルに参加しあって、もし困ってるメンバがいたら助けてあげてください :+1:

Slack上の周知は発言で流されるので、分報チャンネルの一覧とルールについては、Qiita:Teamなどのグループウェアに掲載して、後で見返せるようにしておくといい。

###運用方法
####自分の部屋（チャンネル）に何を書けばいいか？
基本的に何でも書いていいと思います。例えば。

- 今日やること(今日やりたいこと)
- 今日やったこと
- 体調「風邪引いた」「花粉症がひどい」など
- Googleカレンダーとインテグレーションして、その日の個人の予定を流す
- 面白いと思った記事のURLを貼る
- 役立ちそうと思ったGitHubのURLを貼る
- その人向けの記事を見つけたら、その人のチャンネルで教えてあげる
- できたてのUIをスクリーンショットで共有する
- 「ちょっとコンビニ行ってくる」
- 「暑い」「寒い」
- 「○○が面倒くさい」「○○が難しい」
- 「お腹すいた」
- メモ代わりに
- 試行錯誤の過程「○○どうするだっけ？」「○○するんだった」

これやってると日報いらなくなるかなと思ってます。

####誰かに質問するとき、議論するとき、確認する時は
その人のチャンネルに行って話す。

# メリット
・担当者ごとの限定した情報になりにくい（情報の透明化）
　個人の部屋のような概念でチャンネルを作り、そこに質問やメッセージを送ることで、
　今までダイレクトチャットで行っていたやり取りが透明化される。（いつでもだれでも見れるようになる）

・その人にどんなタスクがあってどんなことをやってるかすぐわかる
　「これ誰に確認しようかな」って時にチャンネルでなにやってるかわかると誰に聞くか選定しやすい。
　聞くタイミングとか図れる。
　その人が抱えてるタスクとか進捗とかを把握しやすくなる（マネジメントしやすい）

・２度手間がなくなる
　ダイレクトチャットでやり取りしていたことを第３者に確認された時に、再度伝達するようなことが少なくなる。
　「これどうだっけな...」→（チャンネルを確認）→（あ、ちょうど話してた、解決！）

・ある程度概要を知っておくことでキャッチアップが早くなる


# デメリット
・書く内容、書くタイミングが個々人による
　運用しながらルール決めてくのがいいかなーと思ってます。

・チャンネルの量が増える
　参照するのに時間がかかることもあるかも。
　これどうするのがいいのかな。

# まとめ
導入してみませんか？!!!
Rails(ActiveRecord)とMySQLでutf8mb4を扱う設定

## ActiveRecordから`utf8mb4`を扱えない主な理由

ActiveRecordのstring型カラムが`varchar(255)`で定義されるので、`utf8mb4`ではインデックスのキープレフィックスが767byteを超えてしまう。
> ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

この問題をMySQLの設定とRailsへのパッチで解決する。

## MySQLの設定

文字コードを`utf8mb4`で運用するために、インデックスのキープレフィックスを拡張する。

1. `innodb_large_prefix`を`enable`にする
  * 1を有効にするために、`innodb_file_format`を`Barracuda`にする
  * 1を有効にするために、`innodb_file_per_table`を`enable`にする
* `innodb_default_row_format`を`DYNAMIC`にする # >= 5.7.9

### my.cnfのオプション

```my.cnf
innodb_file_per_table = 1
innodb_file_format = Barracuda
innodb_large_prefix = 1
innodb_default_row_format = DYNAMIC # >= 5.7.9
```

### MySQL5.6

いくつかのパラメータを変更する。

* `innodb_file_per_table`のデフォルトは`enable` (>= 5.6.6)
* `innodb_file_format`のデフォルトは`Antelope`なので、`Barracuda`への変更が必要
* `innodb_large_prefix`のデフォルトは`disable`なので、`enable`に変更する
* `innodb_default_row_format`、**バージョン5.6系にこのオプションは無い**
  * デフォルトが`COMPACT`であり、かつコンフィグから指定できない
  * **テーブル作成時のオプションで指定してやる必要がある**

### MySQL5.7

5.7.9以上であるなら、デフォルト設定でよい。

* `innodb_file_per_table`のデフォルトは`enable`
* `innodb_file_format`のデフォルトは`Barracuda` (>= 5.7.7)
* `innodb_large_prefix`のデフォルトは`enable` (>= 5.7.7)
* `innodb_default_row_format`のデフォルトは`DYNAMIC` (>= 5.7.9)


## Railsの設定

MySQL5.7.9以上を利用しているなら`database.yml`において`utf8mb4`を設定すればよく、とくべつなことをする必要はない。

## `database.yml`の設定

```config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_general_ci
```

MySQL5.7未満では、テーブル作成時に`ROW_FORMAT=DYNAMIC`を渡してやらなければならない。
もしくはカラムオプションかインデックスオプションに`limit: 191`を付けてやる。
> add_index :table1, :column1, length: 191

### Rails4

kamipo神のモンキーパッチを使って、テーブル作成時のオプションに`ROW_FORMAT=DYNAMIC`を追加してやる。
テーブルのCREATEオプションとして`ENGINE=InnoDB ROW_FORMAT=DYNAMIC`を追加してくれる。

```config/initializers/ar_innodb_row_format.rb
ActiveSupport.on_load :active_record do
  module ActiveRecord::ConnectionAdapters
    class AbstractMysqlAdapter
      def create_table_with_innodb_row_format(table_name, options = {})
        table_options = options.merge(:options => 'ENGINE=InnoDB ROW_FORMAT=DYNAMIC')
        create_table_without_innodb_row_format(table_name, table_options) do |td|
          yield td if block_given?
        end
      end
      alias_method_chain :create_table, :innodb_row_format
    end
  end
end
```
参考: http://qiita.com/kamipo/items/101aaf8159cf1470d823

しかし、`db/schema.rb`にダンプされるテーブルオプションには`ENGINE=InnoDB ROW_FORMAT=DYNAMIC`がついていない。
これもまたkamipo神による`activerecord-mysql-awesome`をGemfileに追加しておくと、オプションを正しくダンプしてくれる。

RailsからMySQLのutf8mb4を扱えるようになるまでの道のりは、kamipoさんのおかげで切り開かれたと言っても過言ではないのでとっても感謝です。

### 余談でRails5

beta3ではデフォの状態だとRails4と同様にまだコケる。
kamipoさんのPRがたくさんマージされているので、そのうち。
dockerコンテナに対してループバックアドレスから大量にアクセスすると遅くなった話

こちらのコマンドの出力結果を見て欲しいのですが

```
$ wrk -c300 -d30s http://172.31.23.140/
Running 30s test @ http://172.31.23.140/
  2 threads and 300 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    28.79ms   64.06ms   1.11s    89.38%
    Req/Sec    19.25k     3.29k   31.37k    69.57%
  1149710 requests in 30.04s, 0.91GB read
Requests/sec:  38278.54
Transfer/sec:     31.03MB
```

172.31.23.140はサーバー自身の持っているインタフェースに割り振られたIPアドレスです。
自分自身に向けてwrkコマンドを実行しています。宛先をhttp://127.0.0.1/ に変えると・・・

```
$ wrk -c300 -d30s http://127.0.0.1/
Running 30s test @ http://127.0.0.1/
  2 threads and 300 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    47.57ms  122.82ms   1.26s    92.45%
    Req/Sec    10.78k     2.04k   19.24k    71.83%
  644420 requests in 30.03s, 522.35MB read
Requests/sec:  21458.50
Transfer/sec:     17.39MB
```

え？何でこんなに遅くなるの？
プロセスを見比べると・・・

```
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
17697 root      20   0  269388  10024   3144 S  83.6  0.3   0:24.39 wrk
17668 syslog    20   0   36060   7592   2348 R  55.9  0.2   0:32.85 nginx
17667 syslog    20   0   36160   7572   2348 R  55.6  0.2   0:32.98 nginx
```

```
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
17632 root      20   0  437784  77332  19732 S  88.5  2.0   0:09.86 exe
17702 root      20   0  269388  15344   3100 S  45.3  0.4   0:05.10 wrk
17667 syslog    20   0   36068   7600   2348 R  29.3  0.2   0:37.08 nginx
17668 syslog    20   0   35976   7508   2348 R  29.0  0.2   0:37.28 nginx
```
このPID:17632の`exe`とは何ぞ？とみると

```
docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.18.0.2 -container-port 80
```

**!?**
docker-proxyはホストとコンテナ間のポート転送をかけてるプロセスのようです。
ループバックアドレス宛に大量アクセスした場合にだけ、なぜだかこのプロセスがCPUをたくさん使います。
通常、ループバックアドレス宛てにはアクセスしないので困らないかと思いますが、
dockerでの負荷を計測する際はお気をください。(負荷は外からかけろということですね)
rake task で配列を渡す

`args.extras`ではみ出た引数を配列で受け取れる

```bash
$ bundle exec rake 'hoge[1,2,3,4,5,6]'
```

```ruby:rake_task.rb
task :hoge, [:id] => :environment do |_t, args|
  ids = [args[:id], args.extras].flatten
end
```
sshd_config: RSA認証とPubkey認証の違いメモ


sshd_confを設定している最中に
![Kobito.XYkMlp.png](https://qiita-image-store.s3.amazonaws.com/0/65106/4bca7eac-7e68-a6b6-9b6b-55a17f736382.png "Kobito.XYkMlp.png")
この2行の違いが気になったので調べた結果を残します([参考])．

### RSA認証
Specifies whether pure RSA authentication is allowed.
This option applies to protocol version 1 only.

だそうです．なのでprotocol 1は使わないのでnoでいいかと．

### Pubkey認証
Specifies whether public key authentication is allowed. Note that this option applies to protocol version 2 only.

だそうです．なのでprotocol 2だけ使うときはこちらだけをyesにしとけばいいかと．


[参考]: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man5/sshd_config.5?query=sshd_config&sec=5
serverlessでtwitter認証を作ってみた


# 概要

[serverless](https://github.com/serverless/serverless)を使って、サーバレスにTwitter認証するサンプルを作りました。
https://github.com/abeyuya/serverless-auth

serverlessで似たようなものを作る際の参考になれば嬉しいです。:beer:

# やれること

[サンプル](http://abeyuya.github.io/serverless-auth/)

Twitter認証をして、access_tokenとaccess_token_secretをlambdaで受け取ることができます。

そのtokenをDynamoDBとかに保存しておいて、後で何かAPI叩くのに使ったりする用途等を想定しています。

サンプルでは受け取ったtokenをそのままページに返しています。

# やりたかったこと

こういうやつ: http://dmd.netmarble.jp/

静的なWebサイトなんだけど、「Twitter認証することで何かしらのコンバージョンとする」みたいなことがやりたい場合に、その要件のためだけにサーバサイドを構築するのは嫌だなぁ、というモチベーションです。

# 実装の解説

1. webサイトからこのシステム(/twitter/auth)にリンクで飛んでくる
2. request_tokenとかを取得してTwitter認証画面にリダイレクト
3. Twitter上で認証してもらう
4. callbackでこのシステムに戻ってくる(/twitter/callback)
5. access_tokenを取得する
6. もとのWebサイトにリダイレクトで返す

このシステムはリクエスト受けたら何かしら処理をして、リダイレクトでどこかに飛ばすという流れなので、ユーザに見える画面は無いです。


# Good

上記のような用途ならlambdaとかserverlessはぴったりハマるなと思いました。

* twitter認証された(lambdaが稼働した)分だけしか追加でお金かからない
	* 件数によるけど、よっぽど無料枠に収まるのでは
* たぶん落ちない
	* 負荷とかスケールの問題はAWSに丸投げ
	* ログインユーザ管理とか死活監視とかも考えなくて良い
* マイクロサービスっぽい?ので、別の案件でもそのまま使い回しやすい


# Bad

* serverlessの学習コスト
	* 楽しい
* serverlessのメンテナンスコスト
	* バージョンアップが激しい
	* 一度作ってその後手を入れないなら、あんま気にしなくて良いような気がする



# その他

たぶん似たようなやつ: https://github.com/laardee/serverless-authentication-boilerplate


これはReadmeとかソース読んでみて、Twitter認証に使えるかわからなかったので、結局自分でサンプルを作ってみたといういきさつです。
BlenderでAutomatic Weightの方法

# 作業順

* モデルを作る
* 骨を作る
* モデル、骨の順に選択
* Ctrl + P、「With Automatic Weight」を選択
* Poseモードで骨の動きにモデルがついてくることを確認

# Automatic Weightの特徴

* MirrorはApplyする必要なし
* メッシュが分離していても問題ない

# Bone heat weighting failed to find solution

* objのメッシュに適用すると上記エラーが出ることがある
* シンプルなObjで試すと出なかったのでObjなら起こるわけではない
* Remove double, recalculate Normalしても起こる
* メッシュの一部を削除しても適用できる
* メッシュがどういう状態の時に起こるんだ・・・

# 調査

* 男のモデル　２つともOK
* アイアンマンモデル　２つともNG
chrome 拡張を使って、ajax 通信の url を書き換える

- chrome 拡張で、通信をハックできたので、やりかたを紹介する。
- chrome 拡張の詳細は説明しない。
    - (良い記事を見つけた。[Chrome拡張 | アーキテクチャ - Qiita](http://qiita.com/tbpgr/items/168a90ba07badc86e1e6)。前提知識が全くないのなら、一読すると良いと思う。)

# 背景
- [DocBase - 社内の人も社外の人も、関係者全員で使える情報共有サービス](https://docbase.io/) を使っている。
- 最近、ログイン後のトップページが変更されて、表示件数が減り、情報量が減って残念に思っていた[^2]。
[^2]: 代わりに README 機能が付いた。
- そんなとき、[wamei/chatwork-plugin: チャットワークになんか色々追加するchrome extension](https://github.com/wamei/chatwork-plugin#%E3%82%B9%E3%82%BF%E3%83%B3%E3%83%97%E6%A9%9F%E8%83%BD) に出会った。

そうか！改造すれば良いじゃん :laughing: 

# webRequest を使って、5件の表示件数を20件に書き換える。

トップページの表示件数を増やすことを考える。
「chrome developer tool」のネットワークタブで、URLを確認すると、トップページは
`/api/dashboard_objects?per_page=5&page=1` であることがわかった。
`per_page=20`にすれば、20件になるだろう。

1 . manifest.json に下記を設定する。

```
  "permissions": [
    "https://*.docbase.io/",
     "webRequest",
     "webRequestBlocking"
  ],
```

- [chrome.webRequest](https://developer.chrome.com/extensions/webRequest) を使うと、chrome の通信に干渉できるようになる。
- 今回は url を書き換える必要があるので、`webRequestBlocking` も使う。これを使うことで同期処理となり、url を書き換えられるようになる。

2 . 通信をキャッチして、URLを書き換える

実際に url を書き換えるコードを書く。
- 通信をキャッチするには、`chrome.webRequest.onBeforeRequest.addListener` を使う。
- これにより、`"*://*.docbase.io/api/*"` に対して、`xmlhttprequest` の通信が発生した時、`details`オブジェクトを受け取ることができる。
    - `details.url` に、これからアクセスする url が入っている。
- このとき、`redirectUrl` を返すと、url を書き換えることができる。
- 第3引数に['bloking']が必要。

```
chrome.webRequest.onBeforeRequest.addListener(
  function(details) {
    var url = details.url;
    if (url.indexOf("per_page=5&page=1") > -1) {
      var new_url = url.replace("per_page=5", "per_page=20");
      return { redirectUrl: new_url }
    }
  },
  {
    urls: ["*://*.docbase.io/api/*"],
    types: ["xmlhttprequest"]
  },
  [
    "blocking"
  ]
);
```

以上、これだけで、通信路をハックできた。
全部で100行も行かないだろう。

# まとめ

- chrome 拡張で webrequest を使えば、通信のURLを書き換えることができる。

chrome 拡張がこんなことまで出来るとは思っていなかったので、感動した。
しかもコードはシンプルなので、何にでも使える。
一方で、通信路を書き換えることができるという、chrome 拡張の恐ろしさを改めて感じる経験だった。

# こぼれ話

最初は、`content script`を使って、`location.href` を書き換えるコードを書いていた。
トップページにある「もっと見る」リンクの先のページが、見たいページだったので、トップページに来たらそのページに移動してしまおう、というアプローチだ。

```
$(document).on("ready", function(){
  if(location.pathname == "/"){
    var timer = setInterval(function(){
      $link = $('a[href="/recent"]');
      if(!!$link[0]){
        clearInterval(timer);
        $link.click();
      }
    }, 100)
  }
})
```

このコードは、初回アクセスでは、期待どおりに動作した。
しかし、他のページから遷移してきた時に ready が発火しなかった。
そこで `ajaxComplete`も`ajaxStop` を使おうとしたのだが、
この2つはどちらも発火しなかったので、手も足もでなかった。

とはいえ、これが期待どおりに動いていたら、webRequest には出会わなかったので、
結果的に発火しなくて良かったと思う。

chrome 拡張、凄いな。
CodeIgniter3でHelloWorld

# 前提条件

### ファイルダウンロード
下記から最新のzipをダウンロードする。
https://www.codeigniter.com/download

下記は3.06で動作確認。

zip展開した中身をapacheのDocumentRootにコピー

### ブラウザでのアクセスはこちら
下記のURLにアクセスする。(localhostで実行している場合)
http://localhost/index.php/hello


# Controllerのみ

### クラスファイル作成
下記のとおりhello.phpファイルを作成し、
application\controllers
配下に配置する。

```hello.php
<?php
class Hello extends CI_Controller {

	public function index()
	{
		echo 'Hello World!';
	}

}
?>
```


# Controller/View

hello.phpを書き換える。

```hello.php
<?php
class Hello extends CI_Controller {

	public function index()
	{
		$data = array(
			'title' => 'hello',
			'message' => 'Hello World'
		);

		$this->load->view('helloview', $data);
	}

}
?>
```

helloview.phpを作成し、
application\viewsに配置する。

```helloview.php
<html>
<head>
<title><?php echo $title;?></title>
</head>
<body>
	<h1><?php echo $message;?></h1>
</body>
</html>
```

# Controller/View/Model

hello.phpを書き換える。

```hello.php
<?php
class Hello extends CI_Controller {

	public function index()
	{
		$this->load->model('Hellomodel');

		$data = $this->Hellomodel->getHello();

		$this->load->view('helloview', $data);
	}

}
?>
```

viewは変更なし

hellomodel.phpを作成し、
application\modelsに配置する。

```hellomodel.php
<?php
class Hellomodel extends CI_Model {

	function __construct(){
		parent::__construct();
	}

	function getHello(){
		$data = array(
			'title' => 'hello',
			'message' => 'Hello World'
		);
		return $data;
	}
}
?>
```
超軽量 Docker Image true (125 bytes) と sleeping-beauty (129 bytes)

Docker の軽量なイメージを探していたら `tianon/sleeping-beauty` を見つけたので記事に。
せっかくなので `tianon/true` も含めて説明。

#scratch

Docker で最も軽量なのは scratch で、これはイメージというよりも『何も入っていない』全く空の状態のイメージを指すキーワード。

一切のバイナリが含まれていないため、 

```sh-session
docker run scratch
```

```
Unable to find image 'scratch:latest' locally
docker: Error response from daemon: 'scratch' is a reserved name.
See 'docker run --help'.
```

と実行しても起動することができない。

全く新しい Docker Image を作るときには `scratch` を元に作ると軽量なイメージになる。

```dockerfile
FROM scratch
ADD somefile /
CMD /somefile
```

(この例の somefile の場合、単一バイナリで起動できるように静的リンクにビルドする必要がある。)
Golang では簡単に単一バイナリのプログラムが作れるので、いろいろと試してみると楽しそう。

# [tianon/true](https://hub.docker.com/r/tianon/true/)

Unix コマンドの true のように、実行して終了コード `0` で終了 (成功) するだけのエントリポイントが設定されたイメージ。

Docker Hub によると `perfect for volume-only containers` と書いてある。

```dockerfile
FROM tianon/true
VOLUME /path/to/somedata
```

のように volume だけを持つ空のコンテナが欲しい時に使うと良い。

ちなみにアセンブラで書いてあり、バイナリはわずか 125 bytes のサイズしかない。

[ソースはこちら](https://github.com/tianon/dockerfiles/blob/master/true/true.asm)

驚くほどシンプルな NASM のコードなので、勉強のために読んで見るのも良いと思う。

## ところが

このコンテナは `docker rm` コマンドを使用した場合に、やすやすと消されてしまう。
既に終了してしまっているからだ。

[「Docker のいらないイメージを削除する」 Docker イメージがあるって](http://qiita.com/kitsuyui/items/bd97b96f59e9fc456608) で書いた `docker-gc` でも無慈悲に削除されてしまう。

# [tianon/sleeping-beauty](https://hub.docker.com/r/tianon/sleeping-beauty/)

`tianon/true` は、起動した直後に終了してしまうが、 `sleeping-beauty` はそうではない。

例えて言うなれば `sleep 無限` を実行するような Docker イメージである。
起動してさえいれば `docker-gc` で消されることもない。

こちらもわずか 129 bytes のサイズだ。

[ソースはこちら](https://github.com/tianon/dockerfiles/blob/master/sleeping-beauty/sleeping-beauty.asm)

こちらのソースも単純明快だ。

ちなみに英語で Sleeping Beauty といえば、『眠れる森の美女』のこと。オシャレなネーミングだ。

## まとめ

| 名前 | サイズ | 向いている用途 (私の主観) |
|------|---|---|
| scratch | - | 新しい軽量コンテナを作りたい |
| [tianon/true](https://hub.docker.com/r/tianon/true/) | 125 B | Volume だけのコンテナを作りたい (起動してなくていい) |
| [tianon/sleeping-beauty](https://hub.docker.com/r/tianon/sleeping-beauty/) | 129 B | Volume だけのコンテナを作りたい (起動している必要あり) |
| [busybox](https://hub.docker.com/_/busybox/) | 1.113 MB | [BusyBox のコマンド](http://spblinux.de/2.0/doc/commands.html) さえ使えればいい時 |
| [gliderlabs/alpine](https://hub.docker.com/r/gliderlabs/alpine/) | 4.798 MB | [多種多様なパッケージ](https://pkgs.alpinelinux.org/packages) が要る時 |

※ サイズは 2016 年 4 月 12 日現在のもの。
ScalaでFizzBuzz

## はじめに
FizzBuzzを題材に、一昔前のJavaのような命令型記法から段階を踏んでScalaらしく(関数型っぽく)リファクタリングしてみました。

## if式
書き換えのスタート地点。if式(※)を使って判定を行っている。
※Scalaはifも値を返却するため、if文ではなくif式という。同様にforもfor文ではなくfor式。

```scala:FizzBuzz.scala
for(i <- 1 to 100) {
  if(i % 3 == 0 && i % 5 == 0) {
    println("FizzBuzz")
  }else if (i % 3 == 0) {
    println("Fizz")
  }else if (i % 5 == 0) {
    println("Buzz")
  }else {
    println(i)
  }
}
```

## パターンマッチ＆パターンガード(if)
if式をパターンマッチに書き換え。パターンマッチ内にガード条件(if)を記述することができる。

```scala:FizzBuzz.scala
for(i <- 1 to 100) i match {
  // パターンマッチ & ガード条件
  case i if x % 3 == 0 && i % 5 == 0 => println("FizzBuzz")
  case i if x % 3 == 0 => println("Fizz")
  case i if x % 5 == 0 => println("Buzz")
  case _ => println(i)
}
```

## タプルを使ったパターンマッチ
タプルを使い、判定条件の左辺(剰余計算)と右辺(0)をパターンマッチの入力と判定(case部)に分解する。

```scala:FizzBuzz.scala
for(i <- 1 to 100) (i % 3, i % 5) match {
  case (0, 0) => println("FizzBuzz")
  case (0, _) => println("Fizz")
  case (_, 0) => println("Buzz")
  case _      => println(i)
}
```

## メソッドに切り出す
FizzBuzz変換と出力(println)を分割し、メソッドに切り出す。
呼び出し時に関数合成することで、再利用性が高くなり仕様変更にも柔軟に対応できる。

```scala:FizzBuzz.scala
def fizzbuzz(i: Int) = (i % 3, i % 5) match {
  case (0, 0) => "FizzBuzz"
  case (0, _) => "Fizz"
  case (_, 0) => "Buzz"
  case _      => i
}

// 呼び出し
(1 to 100).map(fizzbuzz).foreach(println)

```
突然のUnbuffered Query…PDO+MySQLで入り込んだ迷宮

CodeIgniterをバージョンアップしたところ、思わぬ形でPHPのバグを踏んでしまいました。

# MySQLのバッファモード
トラブルに見舞われるまで知らなかったのですが、PHPからMySQLを使う場合には、「バッファモード」と「非バッファモード」があります（[リファレンス](http://php.net/manual/ja/mysqlinfo.concepts.buffering.php)）。

* バッファモード…SQLを発行すると、自動的にPHP側へ全データを取ってくる。**デフォルト設定**。
* 非バッファモード…SQLを発行した段階ではまだデータを取ってこない。

一見すると、非バッファモードのほうが便利そうに見えるのですが、1つ大きな問題があります。非バッファモードの場合、一度投げたクエリを始末し切るまで次のクエリが投げられないのです。もちろん、それを意識した上でPDOなりMySQLiなりを直接叩くのであればまだ使いでもあるのですが、（非バッファモードに対応しない）フレームワーク経由でDB接続するとなると、どこでクエリを手仕舞いにするかなどユーザー側で制御できるものではありません。ということで、実質使い物になりません。

# 突然のエラー
CodeIgniter3で開発をしていたところ、ちょくちょくバージョンアップしていたところに置いていかれそうになったので、Composer経由でアップデートを行いました。ところが、アップデートしただけで、画面は白地のエラー画面となって、`Cannot execute queries while other unbuffered queries are active.`というエラーを食らってしまいました。

仮想マシンごと再起動してもエラーが続くので、さらに追いかけてみたところ、CodeIgniter 3.0.4から、MySQL 5.7のデフォルトモード変更に対応するために、接続時に自動実行する`PDO::MYSQL_ATTR_INIT_COMMAND`へ値を足すようになったことが判明しました。

さらに、自分の環境ではAWS RDS接続でもJSTで扱うために[^1]、`PDO::MYSQL_ATTR_INIT_COMMAND`に`SET SESSION time_zone = 'Asia/Tokyo';`というような命令を入れていたのですが、ここで**最後のセミコロン**がトラブルのもととなりました。

なんと、`PDO::MYSQL_ATTR_INIT_COMMAND`にセミコロン区切りで複数のSQL文を渡してしまうと、[勝手に非バッファモードに切り替わってしまう](https://bugs.php.net/bug.php?id=71145)というバグがPDOライブラリにあって、見事にそれを踏んでしまったのでした。

とりあえずセミコロンを外したことで一見落着はしたのですが、思わぬところでいくつも連鎖してトラブルになるものだなと感じました。


[^1]: これを書くために調べていたら、[公式にタイムゾーン切り替えが可能となっていた](http://dev.classmethod.jp/cloud/aws/rds-local-time-zone/)とのことです。
プログラミング未経験でソフトウェア開発者になった3年目社員が社会人生活を振り返ってみる


# 何で今の仕事に就いたの？
プログラミングが好きで今の仕事に就いたわけではないんですよね。
プログラミングができれば食っていくのに困らないんじゃね？みたいなゆるふわな心持ちでした（汗）
継続的に努力し続けることには自信を持っていたので、何とかやっていけるだろうと思っていました。

# で、実際どうなの？
プログラミング技術に関しては心配しなくて良いと思います。
理由は、社内に蓄積されているノウハウやネット検索で大抵のことは解決できてしまうからです。
プログラミング技術よりも、むしろ優れた仕様を定義することのほうが重要です。

# 優れた仕様を定義するために必要なことって何よ？
これに関しては、人によって解釈が異なりますよね。個人的な意見ですが、**ユーザー視点で開発できているか**が重要なポイントであると考えています。
今の業務に例えてみますね。
現在、業務用アプリケーション上で、PDF形式の添付文書（薬剤師向けの薬品情報）を閲覧する機能を実装しています。
添付文書には、全く同じ薬品で製造メーカーが異なるものがあります。（それぞれ添付文書A、添付文書Bとしましょう。）
薬品画像の下に設置したボタンをクリックすると、その薬品の添付文書をPDFで開くことができる機能があるとします。
この場合、添付文書Aと添付文書Bのどちらを開くかをユーザーが選択できるようにしたほうがいいですよね？
けれども、「添付文書には全く同じ薬品で製造メーカーが異なるものがある」という業務知識がなければこちらの選択肢が出てこないのです。
ユーザー視点から技術視点への転換をすることで、開発スキルの向上と実装速度の向上、見積もり精度の向上を実現することができますよ。（上司の受け売りですが。。）

# 休日って何してんの？
図書館にいることが多いですね。読書とか、資格の勉強とか。
他には、体を動かすことが好きなので、水泳とか、フルマラソン出場のためのランニングとかしてます。

# 終わりに
人間は躓くようにできています。
躓いた時こそ、栄養、休養、睡眠をしっかりとること。
焦っている時ほどゆっくりと、ね。
[Ruby] include vs prepend

#**1.Ancestors chain**

クラスAからクラスBをinclude, prepend, inheritancesすると、クラスAとクラスBの間にリンクがあります。クラスAでクラスBのメソッドを実行するために、このリンクに沿ってクラスBのメソッドが探されます。そのリンクは```ancestors chain```と呼ばれています。

```rb
Array.superclass  #=> Object
Object.superclass  #=> BasicObject
BasicObject.superclass  #=> nil
```
以上の例を見ると、クラス```Array```は```Object```から作られました。```Object```は```BasicObejct```から作られました。
RubyにBasucObjectはルートクラスです。
ArrayとBasicObjectの間にリンクがあります。
確認しましょう！

```rb
 Array.ancestors   #=> [Array, Enumerable, Object, Kernel, BasicObject]
```

#**2.Method lookup**
Việc kế thừa cho phép lớp con dùng các method có sẵn từ lớp cha. ```instance variable```でメソッドを実行する際に、最初は```instance variable```のクラスの中に実行したいメソッドを探します。メソッドを探さない場合は、```ancestor chain```に沿ってメソッドを探し続けます。

```ruby
module Basic
  def ping
    p "basic"
  end
end

class RDroom
  include Basic
end

class Team < RDroom
end

class HomeUp < Team
end

homeup = HomeUp.new.ping  #=> "basic"
```

クラス```HomeUp```の```ancestor chain```

```rb
 [HomeUp, Team, RDroom, Basic, Object, Kernel, BasicObject]
```

#**3. include vs prepend**
## - include

クラスAにModuleBを```include```するにしたがって、```ancestor chain```も変えられます. 
ModuleBは含みたクラス/モジュールの右に追加します。

```ruby
module Basic
  def ping
    p "basic"
  end
end

class RDroom
end
RDroom.ancestors
 #=> [RDroom, Object, Kernel, BasicObject]
```

```ruby
module Basic
  def ping
    p "basic"
  end
end

class RDroom
  include Basic
end
RDroom.ancestors 
#=> [RDroom, Basic, Object, Kernel, BasicObject]
```
## - prepend
一方,ModuleBは含みたクラス/モジュールの左に追加します。

```ruby
module Basic
  def ping
    p "basic"
  end
end

class RDroom
prepend Basic
end
RDroom.ancestors
[Basic, RDroom, Object, Kernel, BasicObject]
```

#**3. Lưu ý**
たくさんモジュールをincludeする場合、includeする順番によって、```ancestor chain```を決めます

```rb

module Basic
  def ping
    p "basic"
  end
end

module Company
  def ping
    p "company"
  end
end

class RDroom
  include Basic
  include Company
end
RDroom.new.ping
#=> "company"
```

```RDroom```は```Basic```モジュールを含めると、```ancestor chain```には```Basic```の右に```RDroom```を追加します。変えた```ancestor chain```:

```rb
[RDroom, Basic, Object, Kernel, BasicObject].
```
そして、```RDroom```は```Company```モジュールを含め続けます, ```ancestor chain```には```Company```の右に```RDroom```を追加します。変えた```ancestor chain```:

```rb
 [RDroom, Company, Basic, Object, Kernel, BasicObject]
```
```ping()```を探すとき、```ancestor chain```リンクに沿って、```Company```モジュールの中にメソッドを探します。

```rb
module Basic
  def ping
    p "basic"
  end
end

module Company
  def ping
    p "company"
  end
end

class RDroom
  include Company
  include Basic
end
RDroom.new.ping  #=> "basic"
```

逆に、この場合、```ancestor chain```は,最初```Company```を追加して、Basicを追加します。
変えた```ancestor chain```:

```rb
[RDroom, Basic, Company, Object, Kernel, BasicObject]
```
```ping()```を探すとき、```ancestor chain```リンクに沿って、```Basic```モジュールの中にメソッドを探します。
GitHubのコメントでLINEスタンプライクにLGTM画像を貼り付けられるChrome拡張機能「LTTM」を使ってコミュニケーションを加速させる

#要件
- GitHub初心者でも簡単にLGTM画像を貼りたい
- LGTM画像がアップされてるサイトからURLコピって貼り付けるのがダルい
- コメントでLNEスタンプライクにサクッと画像を添えたい

#Chrome拡張機能「LTTM」を使う
コメントにLGTM画像を簡単に貼り付けられるChrome拡張機能「[LTTM](https://chrome.google.com/webstore/detail/lttm/jdidcgkdggndpodjbipodfefnpgjooeh)」を使う。
<img width="977" alt="スクリーンショット 2016-04-12 17.48.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/6380/e9ff5af8-9988-80f5-7e2f-690aa9431f7b.png">

##使い方

###1.GitHubのコメントエリア（textarea）上で指定キーワードを入力する
![スクリーンショット 2016-04-12 22.07.58.png](https://qiita-image-store.s3.amazonaws.com/0/6380/d3ac80da-0346-0476-c137-130e6ad2a881.png)

###2.表示される画像の候補から貼りたい画像を選ぶ
![スクリーンショット 2016-04-12 22.06.10.png](https://qiita-image-store.s3.amazonaws.com/0/6380/86d9f31c-0b63-0a20-060c-f41646312375.png)

###3.画像が表示される
<img width="415" alt="スクリーンショット 2016-04-12 17.35.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/6380/ac24fc62-beeb-20e2-590f-e7c8e9928765.png">

Looks Good To Me!


## 対応キーワード
!l => LTGMをランダムに検索
!tほげほげ => [tiqav](http://tiqav.com/)から検索
!mほげほげ => [misawa](http://jigokuno.com/)画像を検索
!sほげほげ => [寿司ゆき](http://awayuki.net/sushiyuki/)から検索
!j ほげほげ => [JS Girls](https://github.com/tomo-e/js-girls)から検索
!d ほげほげ => [Decomoji](https://github.com/oti/slack-reaction-decomoji)から検索

[![LTTM (chrome extension)](http://img.youtube.com/vi/jFr1A2a_eeI/0.jpg)](http://www.youtube.com/watch?v=jFr1A2a_eeI)
動画：https://youtu.be/jFr1A2a_eeI

#参考
[Web制作者のためのGitHubの教科書 チームの効率を最大化する共同開発ツール](http://www.amazon.co.jp/dp/4844337009/)
swagger-ui をdockerで使う

[公式](https://github.com/swagger-api/swagger-ui)でもdockerコンテナ使うやり方が書いてあるが、エラーが出てしまいうまく動かなかった。
ローカルにはインストールできたのでDockerfileがよろしくないのか、なんなのか？？

ともあれ、docker-composeで作ってある既存の開発環境に組み込みたかったので、自分でDockerfileを作成して組み込んだメモ。

# Docker Compose　の場合

* ./docker-compose.yml

```shell-session:docker-compose.yml
...
(下記を追記)
swagger:
  container_name: swagger
  tty: true
  build: ./docker/swagger
  ports:
   - "8080:8080"
```

* ./docker/swagger/Dockerfile

```shell-session:Dockerfile
FROM node:wheezy
WORKDIR /var
RUN git clone https://github.com/swagger-api/swagger-ui.git
WORKDIR /var/swagger-ui
RUN git checkout --force refs/tags/v2.1.4
RUN npm install && npm run build
CMD npm run serve
```

* readmeの`Compatibility`で、2.1.4がstableっぽかったので変更しています

# 単体コンテナの場合

`./docker/swagger/Dockerfile`があるとして

```
$ docker build -t api/swagger:v2.1.4 ./docker/swagger
$ docker run -d -p 8080:8080 --name swagger api/swagger:v2.1.4
```

# メモ

jsonはhttp経由で参照する必要があり、別サーバのjsonを参照する場合はjson提供サーバにCOR対応を行う必要があります
ググるのが面倒なら[この記事](http://qiita.com/teratsyk/items/40fc5d8bf58cb2e5002e#%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E5%8F%82%E7%85%A7)の「swagger-ui > ドキュメント参照」を参照してみてください。
Goutteでユーザーエージェントを変更する本当の正しいやり方

[FriendsOfPHP/Goutte: Goutte, a simple PHP Web Scraper](https://github.com/FriendsOfPHP/Goutte)

スクレイピングツールとして有名なGoutteでテスト用クローラー作っていて少し引っかかったことです。

- PHP 7.0.5
- Goutte 3.1

## 問題点

もしかしたらバージョンによって異なるのかもしれませんが、ネットで拾った情報で下記のようにしてUAの変更を試みたところ、ちょっとした不具合がありました。

```php
$client = new Client();
$client->setHeader('User-Agent', 'MyUserAgent')->request('GET', 'http://localhost');
```

これだと、アプリケーション側では変更したUAである`MyUserAgent`が取れますが、Webサーバー（nginx）側のログが`Symfony2 BrowserKit`になってしまいます。

## 検証

`Symfony2 BrowserKit`でソースコードを検索すると、該当箇所が見当たります。

[symfony/Client.php at 3.0 · symfony/symfony](https://github.com/symfony/symfony/blob/3.0/src/Symfony/Component/BrowserKit/Client.php)

```php:symfony/src/Symfony/Component/BrowserKit/Client.php 
/**
 * Sets server parameters.
 *
 * @param array $server An array of server parameters
 */
public function setServerParameters(array $server)
{
    $this->server = array_merge(array(
        'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
    ), $server);
}
```

`Client`生成時にこれによって初期値がセットされ、どうやら`setHeader`では上書きされない模様です。

## 解決策

コンストラクタの引数に渡す方法もありますが、私は頻繁にUAを切り換えて使うので、UAリストを用意し`setUserAgent`というメソッドを生やして扱いやすくしました。

```php:MyClient.php
<?php

/**
 * Class MyClient
 *
 * HTTPクライアント
 */
class MyClient extends \Goutte\Client
{
    /**
     * @var array $ua  ユーザーエージェントのリスト
     */
    protected $ua = [
        'pc.chrome' => 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36',
        'sp.safari' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
        'bot.google' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
    ];

    /**
     * ユーザーエージェントを切り替える
     *
     * @param  string  $platform
     * @return MyClient
     */
    public function setUserAgent(string $platform)
    {
        $this->setServerParameters(['HTTP_USER_AGENT' => $this->ua[$platform]]);

        return $this;
    }
}
```

使い方:

```php
$client = new MyClient();
$client->setUserAgent('pc.chrome')->request('GET', 'http://localhost');
```

これで問題なくできました。
簡単な IP Address の確認

端末のネットワーク設定からの確認やコマンドを叩くのが面倒な場合用

<img width="349" alt="スクリーンショット 2016-04-12 22.13.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/36202/80c16a9a-51d6-de0f-fad9-8ede9e7efece.png">

```html
<html>
  <head>
    <title>IP Address</title>
  </head>
  <body>
    <div>
      <ul id="list"></ul>
    </div>
    <script>
      var RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection;
      var RTCSessionDescription = window.RTCSessionDescription || window.RTCSessionDescription;
      var RTCIceCandidate = window.RTCIceCandidate || window.RTCIceCandidate;
      var config = {"iceServers": []};
      var pc = new RTCPeerConnection(config);
      var addresses = [];
      pc.onicecandidate = event => {
        if (event.candidate) {
          var candidate = event.candidate.candidate;
          if (candidate.match("typ host")) {
            var address = candidate.split(" ")[4];
            addresses.push(address);
          }
        } else {
          var filtered = addresses.filter((element, index, self) => {
            return self.indexOf(element) === index;
          });
          filtered.forEach(address => {
              var list = document.getElementById("list");
              var li = document.createElement("li");
              li.textContent = address;
              list.appendChild(li);
          })
          dataChannel.close();
        }
      };
      var dataChannel = pc.createDataChannel("label");
      var options = {};
      pc.createOffer(options)
        .then(sessionDescription => {
          pc.setLocalDescription(sessionDescription)
            .catch(reason => console.error(reason));
        })
        .catch(reason => console.error(reason));
    </script>
  </body>
</html>
```
VagrantのUbuntu 14.04にSwift 2.2をインストール

# VagrantのUbuntu 14.04にSwift 2.2をインストールします
最近Swiftががんばってるので、このちょっとしたウェーブに乗りたい！

## 準備

* vagrantでUbuntu14.04のBoxを起動

```shell-session:cmd.exe.or.mac.console
mkdir tryswift
cd tryswift
vagrant init ubuntu/trusty64
vagrant up
```

起動したらSSHで入ってください。

## ダウンロードとインストール
```shell-session:vagrant@vagrant-ubuntu-trusty-64
$ sudo apt-get -y update
$ sudo apt-get -y install clang libicu-dev
$ cd /usr/local/src
$ sudo wget https://swift.org/builds/swift-2.2-release/ubuntu1404/swift-2.2-RELEASE/swift-2.2-RELEASE-ubuntu14.04.tar.gz
$ sudo tar xzf swift-2.2-RELEASE-ubuntu14.04.tar.gz
$ sudo mv swift-2.2-RELEASE-ubuntu14.04 /usr/local/swift-2.2
$ cat <<_EOF >> ~/.bashrc 
export PATH=/usr/local/swift-2.2/usr/bin:"\${PATH}"
_EOF
$ . ~/.bashrc
```

## 確認

```shell-session:vagrant@vagrant-ubuntu-trusty-64
$ swift --version
Swift version 2.2 (swift-2.2-RELEASE)
Target: x86_64-unknown-linux-gnu
```

## 反省
GPGのチェックは省きましたごめんなさい。
詳しいことは[Swift.org](https://swift.org/download/#releases)に全て書いてあります。

いつもCentOSなのに今回ははじめてUbuntuを使ってみました。
結果、インストール場所に困りましたが、みなさんホームディレクトリとかに置いたりなんかして適当にやってるみたいなので、あまり気にせずCentOS風に/usr/localに放り込みました。

とりあえずすんなり動いたので、がんばって勉強します！

でも勉強するなら、xcodeでやるのが一番楽ですね。。。。
Swift 3.0 を試す

記事の内容はこちらを参照してください。
https://mishimay.github.io/ae5bd35c619a76c4d772/
<!--



現時点 (2016/04/12) で一番楽そうな方法です。

# 手順

1. Xcode 7.3 をインストール
1. Xcodeの「Preferences...」->「Locations」->「Command Line Tools」が「Xcode 7.3」になっていることを確認
1. [Swift.org - Download Swift](https://swift.org/download/#snapshots) の「Trunk Development (master)
」の「Xcode」をクリックしてpkgファイルをダウンロードしてインストール
  - `/Library/Developer/Toolchains/` フォルダにインストールされる
1. `$ export TOOLCHAINS=swift` する
1. `$ swift --version` で確認 

    ```
    $ xcrun --find swift
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
    $ swift --version
    Apple Swift version 2.2
    $ export TOOLCHAINS=swift
    $ xcrun --find swift
    /Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swift
    $ swift --version
    Swift version 3.0-dev
    ```

# 参考
[apple/swift-package-manager: The Package Manager for the Swift Programming Language](https://github.com/apple/swift-package-manager)


# 備考
他にもswiftenvを使う方法などあると思います。




-->
Railsのメール配信サーバーについてメモ書き


* ActionMailerは、メール送信・受信用のRailsにデフォルトで備わっているgem
* 実際にメール配信するには、SMTPサーバーが必要
* SMTPはメール配信プロトコル
* SMTPサーバーは、自身で用意する場合と外部のSMTPサーバーを使う場合がある


## 自分でSMTPサーバーを構築するケース

```
sendmail
qmail
PostFix
```

* 通常は上記のSMTPサーバーを使ってメール配信を行う。sendmailが一番歴史があり、WordPressの有名なコンタクトフォームの「contact Form 7」というプラグインではWordPressがインストールされているサーバーのsendmailを使って、メールを送信している

小悪魔女子大生のサーバエンジニア日記 » Blog Archive » それぞれのメールサーバー https://co-akuma.directorz.jp/blog/2010/03/%E3%81%9D%E3%82%8C%E3%81%9E%E3%82%8C%E3%81%AE%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC/

## 外部のSMTPサーバーを利用するケース
* 自身でメールサーバーを用意する必要がないので、パフォーマンス面でもいい

* Gmail
	* GoogleのSMTPサーバーを使って配信するケース
	* 通常だとGoogleのログイン規制にかかるので、実用的ではなさそう

* sendgrid
	* クラウド型のメール配信サービス
	* herokuのプラグインでsendgrind用のプラグインがあるので、railsにはsendgridが向いてるっぽい
	* 1日200通まで無料

* Amazon Simple Email Service
	* Amazonが運営するクラウド型のメール配信サービス

## RailsからSendGridを使う
* 以下の記事が一番わかりやすい
* ActionMailer + Sendgrid(SMTPサーバー)でメールを送信できるようにする手順

Cloud Automator | HerokuアドオンのSendGridをRailsアプリから使う http://cloudautomator.com/blog/2014/09/24/sendgrid-with-heroku-and-rails/
円滑にiOS/Android並行開発するための心得まとめ

#円滑にiOS/Android同時開発するための心得まとめ
##■**設計**
###**◇UIパーツやフレームワークはそれぞれの素材・特長を活かす**
**当然ながら共通設計**

- define値やクラス名などを統一する
- 永続化する項目を統一する
- UIデザイン
 - マージンやセンタリングなどのルール統一
 - 端末/画面サイズに応じて、固定/可変する箇所の認識を合わせる

**無理やりiOSのパーツをAndroidに適用しない**

- ダイアログやドラムロール(ピッカー)などのUIパーツ
- iOSのタブ機能はAndroidでは画面上部かサイドメニューを検討
- 戻る機能はAndroidではBackキーを活用

**それぞれの特長を活かす**

- iOSではSQLiteを直接使用せずCoreDataを使用するなど

##■**実装**

###**◇開発者間の情報共有を密にする！**

**LOGの記述体裁を合わせる**

- ファイル名、メソッド名、行数、コメントなど体裁を合わせる
- (ついでに…LOGはデバッグでのみ表示させる)


**TODOの記載の仕方を合わせる**

- 不確定部分や拡張予定の項目は、ミーティングなどで共有したらコメントで残す

**実装中に気がついた例外ケースを共有**

- もう一方でも同じケースが考えられるため

**設計を見直す必要がある場合には共有**

- もう一方でも同じケースが考えられるため自分勝手に直さない！

##**■デザイン**

###**◇画像作成**

**(特に指定がない場合) x1を念頭に、x2、x3の画像を用意する**

- どちらでも必ず使用するため

(参考)

|  iOS  | Android | 解像度 |
|:----------|-----:|------:|
|非Retina   |  mdpi|1px/1pt|
|           |  hdpi|1.5px/1pt|
|Retina(@2x)| xhdpi|2px/1pt|
|Retina(@3x)|xxhdpi|3px/1pt|


- ファイル名にハイフンは使用しない (Androidで使用できない)

##■**PJ管理**

###**◇コーディング規約をメンバーに浸透させる**

**iOSとAndroidで表現が変わらない様にする**

- 例えば：ホーム画面とトップ画面とメイン画面など
 
###**◇iOSとAndroidの工数を同じと思わない**

**Android機種が多く機種依存もあるため、テスト工数も増える**
**傾向的にはAndroidの方が工数膨らみがち**
**見積り時には、サポートするバージョンや機種の合意を取ると良い**
 
###**◇上の諸々の事情をなるべく顧客に知ってもらう**
**無理やり合わせるのは、工数もかかるしバグも生みやすいし、お互い美味しくないですよと伝える**

 - （特にモックをiOSで作成した場合などで）iOSのデフォルトのアニメーションをAndroidに求められて工数増加などがある

##**■もう一歩踏み込むと**

###**◇着手する機能の順番をずらす**

**設計時のスケルトンクラス(ガワにコメントやTODOを記載したもの)を共有する**

- ユニットテストの作成も同様
 

***



まだまだありそうですが、とりあえずこんなところで・・・

https://tech.naturalmindo.com/matome_multiplatform/
DBaaSサービス「Compose」上のPostgreSQL / DB作成・削除を試す

composeでは以前紹介したようにユーザ権限が限定的です。なので、DB作成と削除はWEBブラウザベースのGUIでやるのがスマート。
（ご参考）http://qiita.com/azzeten/items/126c4730b6f8d15ae039
上記リンク先の記事では、データロードをしようとして、admin権限がないことに気づき、別の方法でロードをしたのでした。

今日はGUIでDB作成と削除をする方法をご紹介。
といってもGUIでぽちぽちするだけなので、場所さえ覚えてしまえば一瞬です。

そしてここでいう「DB作成」はcreate database文のイメージです。
先日の記事でご紹介したHA環境を新たにつくる、という話とはまた別で、ひとつのHA環境の中に複数のDB（エクセルでいうとxlsファイル）を作っていくことをやっています。
（ご参考）postgresql by conposeで作るHA構成とは？
　　　　http://qiita.com/azzeten/items/a7a786701cf25ef1a087


## DB作成
左側にある「Browser」をクリックし、右側のボタン「create database」をクリックします。
![s1.png](https://qiita-image-store.s3.amazonaws.com/0/119378/b8da2b1c-efd2-5b9e-2b7e-2c4e22eb5578.png)

GUI上でcreate database文が出てきますので、database名を自分の変えたい内容に修正をして、「Run」をクリックすると、すぐにその内容が反映され、DBが作成されます。以下キャプチャの例では、DB名をtest2とした場合の様子です。
![s2.png](https://qiita-image-store.s3.amazonaws.com/0/119378/d1cfe402-a551-0bf2-9844-7fc85ecbc2f4.png)

## DB削除
DBを消したいときは「Browser」から消したいDB名をクリックします。クリックした後に遷移した画面に「delete database」というボタンが現れるのでそれをクリックします。要はdrop databaseをしてくれるようです。

![s3.png](https://qiita-image-store.s3.amazonaws.com/0/119378/956141fc-5349-3930-f410-42f3589bf9b2.png)


## まとめ
仮にDBを触ったことないアプリの人でも、DB作成削除などの簡単なオペレーションであればWEBブラウザベースのGUIで簡単に作業ができることがわかりました。
DB触ったことないけど、とりあえずアプリからつつけるDB環境がほしい！という人には親切に見える、フレンドリーな画面というか仕様というかつくりかなと思います。
カレントディレクトリ以下の拡張子を数え上げる

```shell-session
find . -type f \
    | perl -F"\/" -ane 'print $F[-1]' \
    | perl -F"\." -ane 'print $F[-1] if $#F > 0' \
    | sort | uniq -c | sort -n
```

実行すると以下の様に拡張子が集計されて
どのようなディレクトリにいるのかが短くまとまったリストで分かります。

```shell-session
     27 txt
     48 tif
     80 psd
     92 mp4
    163 JPG
    459 gif
   1591 jpeg
   2024 png
   3557 jpg

```

このサンプル例ですと、画像を保存するPictureディレクトリ以下に
何故かmp4やtxtがあることが判明します。
ls **/*mp4 や ls **/*txt などの次の行動に繋がります。
カレントディレクトリの新しいテキストを確認する

```shell-session
# ignore more than 3 argument
echo ${1} | grep -P "\D" >> /dev/null \
    && files=3 \
    || files=${1:-3}
echo ${2} | grep -P "\D" >> /dev/null \
    && lines=10 \
    || lines=${2:-10}

head -n${lines} $(file $(ls -t)|grep text|head -n${files}|perl -pe 's/:[^:]*\n/ /')
```

バイナリを無視して新しいテキストの順番にheadで見れます。
ls -t でも最近のファイルは確認できるのですが、
その中身も見てみた方が想起しやすい場面で使います。

引数が無ければ3つの新しいテキストを10行、
1つ目の引数でファイル数を、2つ目の引数でそれぞれの表示する行数を指定できます。
ListViewにObservableArrayListを使う(Android)


kgmyshinさんの
[Data Bindingつかってみた](https://tech.recruit-mp.co.jp/mobile/android-data-binding/)
を参考にして、Data Bindingを試してみた。

各アイテムについてはnotifyPropertyChangedを呼び出すことで、動的に書き換えができる。
ObservableArrayListを使うと追加イベントを監視できるので、アイテムの追加も動的に反映できる。

### ObservableListAdapter

アダプタは、OnListChangedCallbackで更新を教えてもらう
https://github.com/firewood/observable_listview/blob/master/app/src/main/java/info/competitiveprogramming/observablelistview/ObservableListAdapter.java

```java
public class ObservableListAdapter extends ArrayAdapter<SimpleMessage> {
    public ObservableListAdapter(Context context, ObservableArrayList<SimpleMessage> data) {
        super(context, R.layout.list_simple_message, data);
        data.addOnListChangedCallback(new ObservableArrayList.OnListChangedCallback<ObservableArrayList<SimpleMessage>>() {
            @Override
            public void onChanged(ObservableArrayList<SimpleMessage> simpleMessages) {
                notifyDataSetChanged();
            }
```

### MainActivity

リストを作成してListViewのアダプタに設定
https://github.com/firewood/observable_listview/blob/master/app/src/main/java/info/competitiveprogramming/observablelistview/MainActivity.java

```java
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        data = new ObservableArrayList<>();
        adapter = new ObservableListAdapter(this, data);
        binding.list.setAdapter(adapter);
```

追加するとその場で反映される

```java
        SimpleMessage a;
        a = new SimpleMessage();
        a.title = "hoge";
        data.add(a);
```

### サンプル

Addをタップするとアイテムを追加、Changeをタップするとアイテムの中身が変わります。
https://github.com/firewood/observable_listview
SSL証明書のための秘密鍵の作成とCSR作成

## 参考にしたページ
http://nullpopopo.blogcube.info/2015/08/sakurassl-rapidssl.html

## 秘密鍵の作成

2048bit で秘密鍵を作ります。

```
$ openssl genrsa -out my-domain-name.2016.key 2048
```


上記でつくった秘密鍵を使って、CSRを作成します。

## CSR作成
```
$ openssl req -new -key my-domain-name.2016.key -out cert.csr
```

CSRを作成するコマンドのあと、いろいろ聞かれますので、答えます。
以下のものだけ答えれば、そのあとのEmailとかは入力せずにエンターおしていってOKです。

| 聞かれるやつ | 答える例 |
|:-----------|------------:|
| Country Name  |            JP |
| State or Province Name|    Tokyo    |
| Locality Name|             Shibuya |
| Organization Name|         Dantai-no-namae
| Organizational Unit Name | Development-Div |
| Common Name       |        your-domain-name.jp |

以下のページにある説明もわかりやすいです。
[グローバルサインさんのサポートサイト](https://jp.globalsign.com/support/csr/532.html)
[ジオトラストさんのサポートサイト](https://www.geotrust.co.jp/support/ssl/csr/apache_openssl_new.html)
Amazon ECSでCluster Instanceと同じタイムゾーンをTask Definitionに設定する

- [Dockerでホストと同じタイムゾーンをコンテナ起動時に設定する - Qiita](http://qiita.com/ganta/items/a0f34866c994ebaeef69)

のECS版です。

```json
{
  "family": "test-volumes-from",
  "volumes": [
    {
      "name": "localtime",
      "host": {
        "sourcePath": "/etc/localtime"
      }
    }
  ],
  ...
  "containerDefinitions": [
    {
      ...
      "mountPoints": [
        {
          "sourceVolume": "localtime",
          "containerPath": "/etc/localtime",
          "readOnly": true
        }
      ],
      ...
```

Task Definitionの `volumes` でCluster Instance側のパスを指定し、 `containerDefinitions` 内の各コンテナーの設定の `mountPoints` でコンテナー側の `/etc/localtime` に読み取り専用でマウントします。以上。

# おまけ

素のAmazon LinuxをUTC+9にしてecs-agentを入れるUserData

```bash
#!/bin/bash

unalias cp

cp -f -p /usr/share/zoneinfo/Japan /etc/localtime

cat << _EOT_ > /etc/sysconfig/clock
ZONE="Asia/Tokyo"
UTC=false
_EOT_

yum install -y ecs-init
echo ECS_CLUSTER=test >> /etc/ecs/ecs.config
sudo service docker start
sudo start ecs
```

base64 encoded

```
IyEvYmluL2Jhc2gKdW5hbGlhcyBjcApjcCAtZiAtcCAvdXNyL3NoYXJlL3pvbmVpbmZvL0phcGFuIC9ldGMvbG9jYWx0aW1lCmNhdCA8PCBfRU9UXyA+IC9ldGMvc3lzY29uZmlnL2Nsb2NrClpPTkU9IkFzaWEvVG9reW8iClVUQz1mYWxzZQpfRU9UXwp5dW0gaW5zdGFsbCAteSBlY3MtaW5pdAplY2hvIEVDU19DTFVTVEVSPWJhY2tsb2dfYWRtaW4gPj4gL2V0Yy9lY3MvZWNzLmNvbmZpZwpzdWRvIHNlcnZpY2UgZG9ja2VyIHN0YXJ0CnN1ZG8gc3RhcnQgZWNzCg==
```

# 参考

- [Using Data Volumes in Tasks - Amazon EC2 Container Service](http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/using_data_volumes.html)
- [Task Definition Parameters - Amazon EC2 Container Service](http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html)
gitで「Your branch and 'origin/***' have diverged」と言われたときの対処

**（注意）この記事の意味がわからない場合は近所のGitウィザードを呼びましょう**

`git fetch` とか `git pull` とかすると下記のような状態になることがあります。

```
$ git status
On branch foobar
Your branch and 'origin/foobar' have diverged,
and have 5 and 1 different commit each, respectively.
  (use "git pull" to merge the remote branch into yours)
nothing to commit, working directory clean
```

これはどういう状態かというと、リモートブランチとローカルの追跡ブランチとがfast-forwardできない状態になっているということです。上で言えば、共通のコミットから自分の手元では5コミット進んでおり、リモートでは別の1コミットがpushされている状態です。

```
* - * - * - * - * - * - *
      \                 ↑
        *               origin/foobar
        ↑
        remotes/origin/foobar
```

このような状態は普通は起こりません。誰か[^1]が`git push -f`などを実行した可能性が高いでしょう。共同作業中にこのような表示が出た場合は事故の可能性を疑い、関係各所にヒアリングすべきだと思います。このまま無視して作業を続けると誰かのコミットを気付かずに葬り去ってしまうかもしれません。

[^1]: 後述する通り、この「誰か」が自分のこともあります

もちろん、自分で心当たりがある場合は問題ありません。別マシンで自分の見やすさのために歴史改変したような場合であれば、自分の手元の履歴は全て不要ということがわかります。この場合は手元（origin/foobar）をリモート（remotes/origin/foobar）の状態に追従させてしまいましょう。

```
$ git fetch origin
$ git reset --hard origin/foobar
```

くれぐれも、心当たりが無いのに`git reset --hard`したりしないように注意してください。また、他人が作業する可能性のあるブランチ上での`git push -f`も基本的には禁止した方がいいでしょう。
テスト書きすぎ問題を避ける

新しい職場で提案したら歓迎されたので投稿しておく。

---

# テストコード開発方針

漫然とテストコードを書いていると、以下のような問題が発生することがある。

* テストに時間がかかりすぎ、待ち時間が発生したり、テスト結果を見なくなったりする
* テストコードの開発とレビューに時間をかけたが、そのコストに見合う利益を得られない

このような問題を避けるため、以下の方針を定める。

## ビジネス上の価値に比例したテスト

コードの価値をビジネスへの影響や回避方法の有無により以下のようにランク付けする。

* メジャー
    * サービスの主たる機能に影響する
    * 再現条件が広い
    * 回避方法がない／あっても自明でない
* マイナー
	* サービスの副次的な機能に影響する
	* 再現条件が限られる
	* 回避方法がある
* トリビアル
	* サービスには影響しない
	* 違和感はあるが、不便を感じない
	* 回避する必要がない

複数のランクに該当する場合、より多く該当するランクに分類する。

テスト対象がメジャーに該当する場合、より大量の／時間のかかるのテストが許容される。マイナーに該当する場合、最低限の正常系のテストが許容される。トリビアルの場合、テストは書かない。


## インテグレーションテストは最低限

インテグレーションテストの対象は以下のものに限る：

* View - Controller - Model間のインターフェース
* 複数のHTTPリクエストに依存する処理

なお、ViewにはJavaScriptを含む。以下に具体例を挙げる：

* リンク／ボタン／フォームに起因するリクエストパラメータとControllerによるパースの整合
* リクエストパラメータとModelのscopeの整合
* Controllerが生成するインスタンスとViewの表示結果の整合
* 複数のユーザのインタラクション

ただし、インテグレーションテストは低速なので、各対象につきテストは１回に抑える。値を変えた網羅的なテストはユニットテストで行うこと。

## 本来のControllerの責務だけをテスト

Controllerのテストを書く場合、その対象は以下のものに限る:

* 他のクラスのメソッド呼び出し
* HTTPステータスコード
* リダイレクト先URL
* cookies / sessions
* Flash

Controllerが上記以外の処理をしている場合は、その処理を以下の手順で別のクラスに展開する：

1. 問題の処理のテストをControllerテストとして書く
1. 問題の処理を別のクラスに展開する
1. テストを移動する。Controllerのテストでは、新しいクラスの利用だけをテストする。

Controllerが生成しViewで利用するインスタンスのテストは、必要ならインテグレーションテストにする（[assignsとassert_templateはDeprecatedです](https://buildtoship.com/upcoming-changes-in-rails-5-0/#deprecationofassignsandassert_templateincontrollertests)。

## privateメソッドのテストを書かない

privateメソッドのテストは以下の理由で書くべきでない：

* privateメソッドのテストは実装の自由度を下げ、リファクタリングを阻害する
* オブジェクト指向プログラミングでテストすべきはオブジェクト間のインターフェースであり、privateメソッドはインターフェースではない

## テスト対象がやっていない処理はスタブ／モックにする

テスト対象外のオブジェクトが必要な場合はスタブやモックを利用する。

ただし、ControllerがModelのscopeをチェインして利用する場合など、複数の解法がある場合は実オブジェクトを使ってよい。

## コミュニケーション優先

以上の方針よりも開発チーム内でのコミュニケーションが優先される。
GoogleAnalytics, TagManagerを使ったABテスト

#はじめに
ちゃんと書くとものすごく長くなるので、要点絞りまくって書いてます。

#ABテストのやり方
## 1. アプリ起動毎のなにかしらのイベント(GoogleAnalyticsで計測している)のCVRが高いものを選ぶ

この場合は、[GoogleAnalyticsのウェブテスト](https://support.google.com/analytics/answer/1745147?hl=ja&ref_topic=1745207&rd=1)を使います。Webですがアプリでもちゃんと使えます。

詳細はこちらを参考で<(_ _)>
[iOSアプリで、Google AnalyticsのABテスト機能を使う その1](http://qiita.com/mono0926/items/c7abf2503cbccf26c5ab)
[iOSアプリで、Google AnalyticsのABテスト機能を使う その2](http://qiita.com/mono0926/items/a45f2ba268bca964ef9b)
※ その2のいまいちな点に書かれているテストの指標ですが、[GoogleAnalyticsで目標を設定する](https://support.google.com/analytics/answer/1032415?hl=ja)とその目標もここに表示されるので、それを使いましょう。（最初からある指標はまず使うことないと思います。

## 2. ABテストの目的がGoogleAnalyticsの目標に設定できないものの場合
複数の値で検証したい場合だったり、継続率の差を見たい場合とかは、GoogleAnalyticsの目標に設定することができないので、A or B に対応したセグメントをGoogleAnalyticsで作り、それを使って分析します。（※ 1.の場合は自動で結果を出してくれますが、こっちは自分でちゃんと検定なりをしないとだめです。）

まず、A or Bの振り分けですが、これはご自由に。（後述あり
次に、セグメントの作り方ですが、これにはカスタムディメンションを使います。
[カスタムディメンションの設定の仕方はこちら](http://qiita.com/Night___/items/181ed5689b89a23be5e5#推奨カスタムディメンションの設定)
[TagManagerから使う場合はこちら](http://qiita.com/sararilfy/items/ca6543ded2722164e5aa)

（A, Bそれぞれで別のイベントを飛ばして、それを基にセグメントを作ることもできますが、テストの度にイベントが増えていくのはあまりよろしくないと思うので、カスタムディメンションをお勧めします。

カスタムディメンションを設定して、アプリからA or Bを設定したら、セグメントを作るだけです。
新規セグメント作成画面を開き、左のカラムから"条件"を選択、デフォルトで"Flashのバージョン"となっている所から設定したカスタムディメンションを選びます。
![ga.png](https://qiita-image-store.s3.amazonaws.com/0/2343/1f5bd850-ec5c-f380-7ad4-a49e9a24d223.png)

あとはこんな感じで設定すると、GA上のいろんなデータでABの比較ができるようになります。
![a.png](https://qiita-image-store.s3.amazonaws.com/0/2343/a329c8ea-dc5d-30c4-6d34-87e2d06cdb4c.png)
![b.png](https://qiita-image-store.s3.amazonaws.com/0/2343/10fda73c-6231-6d4a-2915-ff9a9037c50e.png)

#TagManagerを使うかどうか
まず、1.のウェブテストを使用する場合は必須です。

2.の場合は、
クライアント側でABを振り分ける or ウェブテストを使う(目標に差が出ないものを設定してテストが勝手に終わらないようにしておく)
のどちらかになりますが、iOSだと後者一択ですね。前者だとテスト結果を全体に反映させるために審査が入ってしまうので。
Androidの場合は審査が無く前者でも特に問題はないので（割り振りの妥当性の検証は必要かも）、アプリのアップデート率や、TagManager導入のコスト（実装、使い方を覚える等）、今後TagManagerを使う可能性があるか等で判断してください。
Ubuntu 14.04にCaffeをインストール(GPU編)

Caffeの導入手順について。
前に書いたのが結構微妙だったので書き直し。(ChainerばっかでCaffeは使って無いけど。)
前のやつ：[Ubuntu14.04にCaffeをインストール(CPUモード)](http://qiita.com/TD72/items/1bab76e395243defcc06)


ubuntu 14.04 上で試しました。
まあ公式HPどおりですが。メモがてら書いてきます。


#CUDAのインストール

```sh
# 最新版をインストール
$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/cuda-repo-ubuntu1404_7.5-18_amd64.deb
$ sudo dpkg -i cuda-repo-ubuntu1404_7.5-18_amd64.deb
$ sudo apt-get update
$ sudo apt-get install cuda
```
## cuDNN
cuDNNを導入すると速くなるらしい。(NvidiaのDeveloper登録が必要)
入れなくても可。

```sh
# 登録してブラウザからダウンロード
$ tar xvf cudnn-7.5-linux-x64-v5.0-rc-tgz
$ sudo cp cuda/include/cudnn.h /usr/local/cuda/include
$ sudo cp cuda/lib64/* /usr/local/cuda/lib64
```

# 依存関係のインストール

```sh
$ sudo apt-get install libatlas-base-dev libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
```

# Caffe のダウンロード

```bash
# gitが入ってなければ
$ sudo apt-get install git

# home直下に置きます。わかる人は好きなところにどうぞ。
$ cd
$ git clone https://github.com/BVLC/caffe.git
```
#Makefile.config の設定
cudnnを使わないならそのままでOK

```bash
$ cd caffe
$ cp Makefile.config.example Makefile.config
```
cnDNNを使うなら5行目をアンコメントアウト

```makefile:Makefile.config
# USE_CUDNN := 1
↓
USE_CUDNN := 1
```
# コンパイル
`$ make -j4 all` のようにすると並列処理ができる。数字はCPUのコア数。
時間がかかるのでフルパワーでやるのがおすすめ。

```bash
$ make all
$ make test
$ make runtest
```
テストが全部パスできればcaffeの環境構築は終了。
失敗した時は、問題を解決してから `$make clean`をして`$make all`からやり直し。

# Python でCaffe を使うための環境構築

python系

```bash
$ sudo apt-get install python-dev python-pip python-numpy python-skimage gfortran
```
pipで必要なライブラリのインストール

```bash
$ sudo pip install -r ~/caffe/python/requirements.txt
```
コンパイル

```bash
$ make pycaffe
```
パスを通す。(bashの例)

```bash
$ echo 'export PYTHONPATH=~/caffe/python/:$PYTHONPATH' >> ~/.bashrc
# 反映させる
$ source ~/.bashrc
```
あとは

```bash
$ python
>>> import caffe
```
でcaffeが読み込まれればOK。
矢の動き

矢が飛んでいくのに合わせて、角度がつくようにします。


```csharp:arrow.cs

[SerializeField]
Transform t;

[SerializeField]
float step;

void FixedUpdate () {
    //弓矢のうごき
    Vector3 vel = rbody.velocity;
    float angle = Mathf.Atan2 (vel.y, vel.x) * Mathf.Rad2Deg;
    //new Vector3(0, 0, 1)はカメラの角度によって変えると自然になるかもしれません。
    Quaternion quaternion = Quaternion.AngleAxis (angle, new Vector3(0, 0, 1));
    t.rotation = Quaternion.RotateTowards (t.rotation, quaternion, step*Time.deltaTime); 
}


```