OmniAICreator/Qiita-1.07M huggingface dataset:
情報のキャッチアップ力を少しだけ上げる方法

[株式会社LITALICO](http://litalico.co.jp/)　[LITALICOワンダー](https://wonder.litalico.jp/)事業部　
サービス開発グループ　エンジニアの[@tomotomospot](https://qiita.com/tomotomospot)です。
この記事は『LITALICO Advent Calendar 2017』19日目の記事です。

## はじめに
エンジニア系のニュースは自分から欲しい情報を仕入れる工夫をしないと、
スピーディーに手に入れることが難しいです。（気づいたら行きたいイベントが終わっていた）とか

じゃあ色々ニュース系のアプリを入れれば…という事になりがちですが、
通知がすごい来て、かつ余分な情報だとかなり面倒です。

今回は今まで会ってきた人の情報収集を参考に
自分なりの情報収集方法などを一部紹介できればと思います。

## まずは欲しい情報と仕入れるタイミングをざっくり整理する。

私の場合は欲しい情報を整理して、いつ情報を仕入れるかざっくりと決めています。

- 欲しい情報
 -  ガジェット系
 -  業界のリアルな話
 -  IT系の旬な話
 -  パイオニアの話し

- いつ情報を仕入れるか
 -  速報系
 -  通勤時などにまとめて系
 -  定期配信系
 -  実際に会いに行く

#  速報系

速報系は【AppleWatch】を活用して通知をコントロールしています。
デフォルトの通知設定だと、やれ「深呼吸しましょう！」とか「そろそろ起立の時間です」と
しんどい通知が来るのでぬーってなります。必要に応じてアプリの通知をコントロールしましょう。
※Twitterの通知は結構使います。フォローしている方のつぶやきに迅速に反応できたりします。

・　1.[Webエンジニアがフォローしておきたいアカウントリスト](http://nesheep5.hatenablog.com/entry/2017/08/08/154318)
興味ある人のSNSアカウントをフォローして通知をONにしている。
このリスト以外にも何人かいますが、省略。

・　2.[gori.me](https://gori.me/)
ガジェットの情報発信といえば安定のgori.me　 もちろん通知ON

# 通勤時などにまとめて系

・　1.[モヒカンslack　チャンネル一覧](https://gist.github.com/kotakanbe/e4232407b75e1ec584e7)
SlackのIT系情報取得最強コミュニティの【モヒカン】！！色々チャンネルがあるので、
好きなチャンネルに参加しよう！入りすぎるとカオスになるので注意。

・　2.[CodeIQ MAGAZINE](https://codeiq.jp/magazine/)
 現場取材系記事を主に。

・　3.[宮川達彦氏のポッドキャスト Rebuild.fm](http://rebuild.fm/)
技術、ガジェットなどの最新ネタについての話を聴く

・　4.[スライドシェア](https://www.slideshare.net/)
イベント／勉強会に行けなかったときはスライドシェアで追っかける。

・　5.SNS(Facebook／Twitter)
Facebookはグループやページから情報を仕入れる事が多いです。
Twitterは通知以外のフォローしている方をざっくり読んでます。


# 定期配信系

・　1.盲点的存在　 [Google アラート](https://www.google.co.jp/alerts)
　　　Googleアラートなら期間を指定して、最新の情報を仕入れることができます。
　　　メール通知の設定も選べるので、通知の頻度多すぎで辛いみたいな人でも気軽に使用できます。
　　　[Googleアラートを『最強の最新情報収集ツール』として使う『設定と使い方』](http://wepli-dot2.hatenablog.com/entry/Google-Alert)
　　　キーワードを指定することで引っかかった最新情報をメールで通知してくれます。
　　　【iPhone】や【プログラミング教育】とかで設定してます。

＜画像↓＞

<img width="762" alt="スクリーンショット 2017-12-14 17.54.03.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/47901/ed4ebe43-bc90-7523-0c1a-e56616324476.jpeg">

　　※こんなイメージ
　　[GoogleアラートとSlackで気になるニュースをキャッチ](http://amikodomolabo.org/2017/11/17/google%E3%82%A2%E3%83%A9%E3%83%BC%E3%83%88%E3%81%A8slack%E3%81%A7%E6%B0%97%E3%81%AB%E3%81%AA%E3%82%8B%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9%E3%82%92%E3%82%AD%E3%83%A3%E3%83%83%E3%83%81/)
　　メールとか見ないみたいな人は Slackに飛ばすこともできます。

・　2.[TECH PLAY](https://techplay.jp/)
スケジュールを見てくれたり、興味のあるタグを選ぶだけで新着イベント情報／勉強会情報が毎日届くのでオススメ。

# 実際に会いに行く
かなりハードルが高いように思いますが、イベントの懇親会などで話せる機会なども多いので
少しだけ勇気振り絞って行く。が良いです。（笑


## さいごに

欲しい情報は人によって様々かと思いますが、参考になれば幸いです。

さいごのさいごに自社アピール。
・　[マインドがあればスキルは身につく--IT×ものづくり教室「LITALICOワンダー」](https://japan.cnet.com/article/35111588/)
・　[＜アルバイト・インターン＞IT×モノづくり教室の指導員大募集！](https://www.wantedly.com/projects/10425)

LITALICOワンダーにご興味ある方は気軽にFacebookのメッセージでも飛ばしてくださいませ。


明日の『LITALICO Advent Calendar 2017』は
同じくLITALICOワンダー　サービス開発Gの[@saorinrinrin](https://qiita.com/saorinrinrin)の登場です！
内容は【Scratch世代の子どものための"Hello,world!"に代わる一行を考える】　
お楽しみに＼(^o^)／
TensorFlow 入門1

#環境
　Mac

##Homebrew インストール
　公式ページからスクリプトをコピー
　　https://brew.sh/index_ja.html
　　　↓
　　　/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

　アップデート
　　brew update

#pyenv-virtualenvインストール
```
$ brew install pyenv-virtualenv
```
　
```
$ vi ~/.bash_profile
```
に以下を追記

```
export PYENV_ROOT="$HOME/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
  export PATH="$PATH:$HOME/.pyenv/bin"
  eval "$(pyenv init -)"
  eval "$(pyenv virtualenv-init -)"
fi
```

#pythonインストール
```　
$ pyenv install anaconda3-5.0.1
```
#仮想環境作成
「tensorflow」
```
$ pyenv virtualenv anaconda3-5.0.1 tensorflow
```

#

















#参考
https://qiita.com/uhooi/items/b2f3a121b2e9dac6a256
https://qiita.com/rabbit1013/items/1494cf345ff172c3b9cd
【復旧編】Windows 7のセーフモードで Microsoft Windows Installer を無理矢理使ってソフトウェアをアンインストールする方法

#概要
ウイルス対策ソフトを利用する案件で次の事例にぶち当たりました。FFRI社が販売しているyaraiというウイルス対策ソフトは他社製品との併用をサポートしているのですが、次の組み合わせだとyaraiがwinlogon.exeに干渉するため、OSが不安定になってしまい、使い物にならなくなるのです。

* Windows 7 32-bit
* FFRI yarai 2.5.x
* McAfee Endpoint Security 10.5.1

セーフモードで端末はかろうじて起動するようにはなるのですが、こんどは FFRI yarai 2.5.x や McAfee Endpoint Security 10.5.1 を削除する術が通常でありません。なぜなら、セーフモードではMicrosoft Windows Installerサービスが停止しているため、コントロールパネルの「プログラムと機能」からアンインストールしようとすると、次のような警告が表示されてしまうからです。

![safamodemsierror.jpg](https://qiita-image-store.s3.amazonaws.com/0/114856/6a34ce29-33e6-8043-1ff2-1273076cd25b.jpeg)
((C) [「セーフモードで Windows インストーラ サービスを利用できるようにする方法」](http://pasofaq.jp/controlpanel/appwiz/safemoderunmsi.htm))

なので、FFRI社が提供する強制削除ツールを使用するなどする必要があります。ですが、そういうツールを使わないで Microsoft Windows Installer を起動する方法がありました。[「セーフモードで Windows インストーラ サービスを利用できるようにする方法」](http://pasofaq.jp/controlpanel/appwiz/safemoderunmsi.htm)がそれです。そのページには「Windows 7 では、下記の設定を行ってもセーフモードで Windows インストーラ サービスを利用することはできません。」と書かれていますが、Windows 7 32-bit では Microsoft Windows Installer を起動することができ、少なくとも FFRI yarai はアンインストールできました。今回は、その詳細についてご紹介します。

なお、この記事で書いている内容は私の知る範囲では Microsoft 社が公式にサポートしているわけではなく、あくまでも裏技です。ですので、実施する場合は、自己責任で行なってください。また、Windows 7 32-bit のみでしか検証しておりません。

#セーフモードで Microsoft Windows Installer を起動させる方法
##レジストリーキーを追加
まずレジストリーキーを追加します。通常のモードと手順は同じで次の通りです。

1. [スタート]のボタンを押し、[プログラムとファイルの検索]欄に「regedit」と入力し、[Enter]キーを打ちます。
![1.regedit指定.PNG](https://qiita-image-store.s3.amazonaws.com/0/114856/0791f90d-4a5d-1925-e57d-a162d1475ae7.png)  

1. レジストリエディタが起動されたら、次のキーを探します。
&nbsp;HKEY_LOCAL_MACHINE
&nbsp;&nbsp;SYSTEM
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CurrentControlSet
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SafeBoot
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Minimal
1. 探した Minimal を右クリックし、[新規]-[キー]をクリックします。![6. 新規キー追加.PNG](https://qiita-image-store.s3.amazonaws.com/0/114856/33229df3-553a-8d2c-017b-3bee61461a91.png)  
![7. 新規キー追加直後.PNG](https://qiita-image-store.s3.amazonaws.com/0/114856/9777e5ee-4830-e53f-8381-8fa65192c5da.png)
1. 新しく追加したキーの名前を「MSIServer」に変更します。![9. 名前変更直後.PNG](https://qiita-image-store.s3.amazonaws.com/0/114856/b4539c4d-7482-2327-b63d-db4c3fdaff48.png)

1. 画面右側の（既定）をダブルクリックし、値のデータに「Service」と入力して [OK] をクリックします。![10. 文字列の編集.PNG](https://qiita-image-store.s3.amazonaws.com/0/114856/dd67d2c6-c5ff-b26a-1550-1a78ad39de76.png)

##プログラムのアンインストール
ここから通常と同じ方法でアンインストールできます。
ただし、通常は使わないレジストリーキーを設定しているので、再起動前に次の後処理をするのが賢明です。

##後処理
先ほど設定したレジストリーキーを削除します。
1. 作成した MSIServer を右クリックし、[削除]をクリックします。![12. レジストリーキー削除.png](https://qiita-image-store.s3.amazonaws.com/0/114856/75b7953c-17dc-3238-0bad-469fe160f9c6.png)

#最後に
上記の方法はあくまでも最後の最後の手段だとお考え下さい。
またWindows 7 64-bitでは未検証です。
そこは御留意ください。

なお、FFRI yaraiはバージョンを2.7.x以上にすればMcAfee Endpoint Securityと共存可能です。
UnityでFinal IKを使ってみた時のメモ


昔はC#をメインで使ってたのでホームに帰ってきた気分。
unityのIDEさえ覚えれば使えるようになる。
ゲームプログラマにとっては当たり前の操作なのかもですが、
あまり関節とか意識することがなかったので勉強しようと思ってアセットを買いました。


Final IK
https://www.assetstore.unity3d.com/jp/#!/content/14290

とりまこれでいいだろうと思って買いました。
ちょっと前まで半額だったそうで、良さげのアセットは半額のうちに買っとけって感じみたい。

#まずはボールに向かってパンチ

##実行してみる

Aim IKをダブルクリック。

![スクリーンショット 2017-12-16 午後1.13.22.png](https://qiita-image-store.s3.amazonaws.com/0/64334/99494963-e0aa-631f-c729-adcab3ade186.png)

▷の実行ボタンを押すと動く。

![スクリーンショット 2017-12-16 午後1.21.55.png](https://qiita-image-store.s3.amazonaws.com/0/64334/79cb0db8-5a20-ae30-7747-7df1ad834126.png)

![スクリーンショット 2017-12-16 午後1.24.57.png](https://qiita-image-store.s3.amazonaws.com/0/64334/d6853e87-e4ba-8cfd-9a49-f16596682c63.png)

![スクリーンショット 2017-12-16 午後1.25.18.png](https://qiita-image-store.s3.amazonaws.com/0/64334/0f6e0593-042e-ab2a-c386-1998a8e20c16.png)

unityではGameObject.GetComponentを使わないと呼べないオブジェクトとGameObject.GetComponentを使わなくても呼べるオブジェクトがあるようです。
https://docs.unity3d.com/jp/540/ScriptReference/GameObject.GetComponent.html

Transformとかは使わなくても呼べる系でpublic Transformと言う感じで直で呼べてます。
ボールのpositionに向けてアニメーションを実行する流れ。

![スクリーンショット 2017-12-16 午後1.26.40.png](https://qiita-image-store.s3.amazonaws.com/0/64334/bd755089-6c7e-58c1-5c29-bfebdeabe9d7.png)


```cs:
		public AimIK aimIK; // Reference to the AimIK component
		public Transform pin; // The hitting point as in the animation
		
		void LateUpdate() {
			// Rotate the aim Transform to look at the point, where the fist hits it's target in the animation.
			// This will set the animated hit direction as the default starting point for Aim IK (direction for which Aim IK has to do nothing).

			print (pin.position);

			aimIK.solver.transform.LookAt(pin.position);

			// Set myself as IK target
			aimIK.solver.IKPosition = transform.position;
		}
```


![スクリーンショット 2017-12-16 午後1.17.23.png](https://qiita-image-store.s3.amazonaws.com/0/64334/43c7c400-3606-3956-f7e9-c0274f7e8b5e.png)

![スクリーンショット 2017-12-16 午後1.17.53.png](https://qiita-image-store.s3.amazonaws.com/0/64334/58608c87-72f8-ce10-550a-c1a0eb5db92d.png)

![スクリーンショット 2017-12-16 午後1.18.18.png](https://qiita-image-store.s3.amazonaws.com/0/64334/6d040f4b-e227-beb2-5749-89e4b5302244.png)

boxingボタンをクリック。
motionの右の青色のポチを押すとselect motion画面が現れてモーションを変更できる。

![スクリーンショット 2017-12-16 午後1.19.57.png](https://qiita-image-store.s3.amazonaws.com/0/64334/c741db71-70cd-aa0c-ccf6-045d7239d972.png)

モーションを変更できる。

![スクリーンショット 2017-12-16 午後1.20.12.png](https://qiita-image-store.s3.amazonaws.com/0/64334/626be084-6320-3f3c-c6c4-e14eb3e0cc42.png)

サイド実行するとモーションが変わってる。


#運転する

![スクリーンショット 2017-12-16 午後3.05.30.png](https://qiita-image-store.s3.amazonaws.com/0/64334/68cd9228-e009-2b2c-d862-38cbca696ad5.png)


おそらくFull Body Biped IKにてrigを操作してる。
あとはanimatorにidleがついてるので、なんもしてないけどたまに揺れる動きをする。

![スクリーンショット 2017-12-16 午後3.04.03.png](https://qiita-image-store.s3.amazonaws.com/0/64334/8021d974-d51c-3af2-f8c8-db3970c3145d.png)
GoogleHomeの初期化方法

## GoogleHomeの初期化（工場出荷状態に戻す）方法

　画像はminiを使用しています。

GoogleHomeをひっくり返す

![Photo_17-12-16-14-12-23.423.jpg](https://qiita-image-store.s3.amazonaws.com/0/183354/de00651b-cc76-1bda-b8c2-7196f8774a95.jpeg)
（背面の画像です）

背面の「G」というマークと電源ケーブルの間にある〇を押し続ける

![Photo_17-12-16-14-12-21.819.jpg](https://qiita-image-store.s3.amazonaws.com/0/183354/c146e456-9510-54f9-2d12-f1196f233128.jpeg)

3秒ほど押し続けるとgoogleHomeから「初期化をしようとしています」と聞かれるのでキャンセルする場合はボタンを離し、初期化する場合は音声に従い押し続けることで初期化することができます。
Pytestの基本的な使い方


##pytestのインストール
```bash
$ pip install pytest
```
まずは上記のコマンドでインストールします。

##作成したテストの実行方法
###特定のファイルのみ指定してテストする場合
```bash
$ pytest test_sample001.py
```
上記のコマンドでテストを実行します。
オプション等...
-s テスト内で実行されたprint()をコンソールに表示

###同一ディレクトリ配下のテストファイルを全て実行する場合
```
.
├── test_sample001
├── test_sample002
└── test_sample003
```
このようなディレクトリ構成の中で　pytest . を実行すれば頭に test_ で始まるファイルを全て実行してくれます。

##モジュール内の関数をモックにする場合
```python3:test_sample001.py
import sys

current_module = sys.modules[__name__]

def bar():
    return 'bar'

def test_bar(monkeypatch):
    monkeypatch.setattr(current_module, 'bar', lambda: 'patched')
    assert bar() == 'patched'
```
今回は同一モジュール内の関数をモックに置き換えるのでcurrent_moduleに現在実行中のモジュールを与えておく。
monkeypatchをテスト関数の引数として読み込む。
このテストでは関数barを'patched'を返す関数に置き換えている。


##クラス内のメソッドをモックにする場合
```python3:test_sample002.py
import sys

current_module = sys.modules[__name__]

class Piyo:
    def piyo_func(self):
        return('piyo')

def hoge():
    piyo = Piyo()
    return piyo.piyo_func()

def test_hoge(monkeypatch):
    monkeypatch.setattr(current_module.Piyo, 'piyo_func', lambda *args: 'patched')
    assert hoge() == 'patched'
```
この例ではPiyoクラスのpiyo_func()をモックに置き換えて'patched'を返却するようにしています。


##クラス自体をモックに置き換える場合
```python3:test_sample003.py
import sys

current_module = sys.modules[__name__]

class Foo:
    pass

def bbb():
    foo = Foo()
    return foo.foo_func()

def test_bbb(monkeypatch):
    class DummyFoo:
        def foo_func(self):
            return 'patched'

    monkeypatch.setattr(current_module, 'Foo', DummyFoo)
    assert bbb() == 'patched'
```
FooをモックのDummyFooに置き換えて、foo_funk()を実行しています。

##monkeypatch.setattrメソッドの説明
###monkeypatch.setattr(a, b, c)
a:モックにしたい[関数, クラス]を含む[モジュール, クラス]
b:モックにしたい[関数名, クラス名]
c:モックの[関数, クラス]
Docker概要2 - アーキテクチャ

# はじめに

一連の[Docker概要](https://qiita.com/Imyslx/items/7bfd4d7962557efc367d)記事の大きな目的は以下の2点です。
社内用に適当に書いた資料ですが何かの役に立つかもしれないのでこちらにも投稿しておこうかなっていう記事です。

* Dockerについての情報を、教育目線でまとめることでDockerに対する理解を深めること。
* 社内のDocker普及を目的として、ざっくりとした概要を社内のドキュメント環境に設置しておくこと。

# 今回の記事について

　[前記事](https://qiita.com/Imyslx/items/7bfd4d7962557efc367d)で概要に触れたので、アーキテクチャについてもう少し深く触れていきます。
　凡そは[docker-docs-jp](http://docs.docker.jp/engine/docker-overview.html#the-docker-platform)に則りつつ、ほしい情報などを継ぎ足していく形になっています。

# 設計思想

　アプリケーションをインフラから分離し、アプリケーションを管理するようにインフラを扱えるようにします。コードの移動をより速く、テストを速く、デプロイを速くし、コードの記述とコードの実行におけるサイクルを短くします。
　コンテナはこれを実現するための機能の一つで、あらゆるアプリケーションをコンテナ内で安全に分離して実行します。

# アーキテクチャ

　Docker はクライアント・サーバ型のアーキテクチャです。とはいえ、クライアントとサーバは同一OS上で稼働させることも可能です。

## クライアントサイド

　ユーザがDockerの管理に利用します。コマンドを受け付けるとDockerホスト上のEngineデーモンに処理を依頼します。

## サーバサイド

　前述したDockerホストに当たります。DockerのEngineデーモンが稼働しており、ホスト内に存在するDockerイメージの管理・Dockerコンテナの管理を行います。

# DockerEngineの構成要素


![アーキテクチャ](http://docs.docker.jp/_images/architecture.png)
![アーキテクチャ](http://docs.docker.jp/_images/engine-components-flow.png)

## Dockerイメージ

　前述しましたが、Dockerコンテナの基盤となる、読み込み専用のテンプレートです。Dockerコンテナの作成時に読み込まれ、差分を管理することでディスクコストを削減しています。
　このイメージはレイヤをOverlayすることで積み重ねて構成されており、前述したaufsによってUnionMountされることで単一のストレージとして動作するように見せかけています。
　Dockerイメージを更新する際はこのレイヤを新しく構築する(Commit)ことで行われ、その他のコンテナを更新する際もこのレイヤを適用することで行われるため非常に高速です。

## Dockerレジストリ

　Dockerイメージを保管します。パブリックもしくはプライベートに保管されたイメージの管理をしており、アップロードやダウンロードが可能です。
　パブリックなDockerレジストリとして [Docker Hub](http://hub.docker.com/) が利用可能です。または自身で構築したレジストリも利用できます。

## Dockerコンテナ

　アプリケーションの実行に必要な全てを持つ、Dockerイメージから構築された一つのプラットフォームです。Dockerクライアントによって開始停止・移動削除などが可能です。
　コンテナにはOS、ユーザが追加したファイル、メタデータを含んでいます。
　イメージのランタイム・インスタンス（runtime instance；実行状態にあるモノ）です。言い換えれば、イメージからメモリ内に展開し、実際に実行する何かです。

### Dockerコンテナの実行

Dockerクライアントにて以下のコマンドを実行しましょう。

$ docker run -i -t ubuntu /bin/bash

runオプションによってコンテナの起動命令を発行しています。
最後の `/bin/bash` で起動したコンテナ内でBashの起動を指示しています。

# リソースの管理

DockerはLinuxシステムに於けるcgroupという機能によってコンテナ毎のリソースを管理します。cgroup により、ユーザーは、CPU 時間、システムメモリー、ネットワーク帯域幅などのリソースやそれらのリソースの組み合わせを、システム上で実行中のユーザー定義タスクグループ (プロセス) の間で割り当てることができるようになります。
　[RedHat](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/resource_management_guide/ch01)
[javascript] Moment.jsで日付フォーマットなど 日付系処理を楽にする


# 背景
GitHubにおいて、現在(2017/12)日付を処理するライブラリの中で
多分 **一番Starがついてる日付系のライブラリ**。

# 概要
Moment.jsはJavaScriptの **Dateオブジェクトをラップするオブジェクト**を生成して、
そのオブジェクトに日付処理を任せることが出来る。
使い方はDateオブジェクトの代わりにmoment()を呼び出してMomentオブジェクトを生成するだけ。

# インストール

```
npm install moment   # npm
```

# 使い方

## (1) 現在時刻を文字列で取得

```js
moment().format();                                // "2014-09-08T08:02:17-05:00" (ISO 8601)
moment().format("dddd, MMMM Do YYYY, h:mm:ss a"); // "Sunday, February 14th 2010, 3:25:50 pm"
moment().format("ddd, hA");                       // "Sun, 3PM"
moment('gibberish').format('YYYY MM DD');         // "Invalid date"
```

その他の `format` 設定は[こちら](http://momentjs.com/docs/#/displaying/format/)まで。

## (2) 文字列からmomentを生成する

```js
moment('2017-12-12');
```

## (3) Dateオブジェクトからmomentを生成する

```js
moment(new Date('2017-12-12'));
```

## (4) オブジェクトからmomentを生成する

```js
moment({years: 2017, months: 12, days: 12, hours: 7, minutes: 7, seconds: 7})
```

## (5) 配列(ARRAY) からmomentを生成する

```js
moment([2014, 7, 8])           // Array
```

## (6) UNIX時間からmomentを生成する

```js
moment(1404817278000)          // UNIX時間 (ミリ秒)
moment.unix(1404817278)        // UNIX時間 (秒)
```

## (7) momentをDateオブジェクトに変換する

```js
var now = moment();
console.log(now.toDate()); // Dateオブジェクトが返される
```

## (8) unix timestampで取得

```js
moment().unix() 
```


## (9) ISO8601 フォーマットの文字列で取得

```js
moment().toISOString() // `2014-07-17T10:00:00.964Z` ISO8601 フォーマットの文字列で取得
```

## (10) UTC

```js
moment("2014-03-01 12:00:00").utc().format();
moment.utc("2014-03-01 12:00:00").format();
```

## (11) 日付を比較

```js
moment('2010-10-20').isBefore('2010-10-21'); // true
moment('2010-10-20').isBefore('2010-12-31', 'year'); // false
moment('2010-10-20').isSame('2010-10-20'); // true
moment('2010-10-20').isSame('2010-01-01', 'year');  // true
moment('2010-01-01').isSame('2011-01-01', 'month'); // false, different year ２番目のパラメータは比較単位を指定できる（`month`と指定する場合は、 `year`と`month`をチェックする）
moment('2010-01-01').isSame('2010-02-01', 'day');   // false, different month
```

`isBefore` 関数とセットで `isAfter`、`isSameOrBefore`、
`isSameOrAfter`、`isBetween` 関数も用意されている。

## (12) 差分を計算する

```js
var fromDate = moment('2014-01-01 0:00');
var toDate   = moment('2015-01-01 12:00');
toDate.diff(fromDate, 'days'); // 365
// 第三引数にtrueを渡すと少数まで計算してくれる
toDate.diff(fromDate, 'days', true); // 365.5

// 第二引数を省略するとmsを返す
toDate.diff(fromDate); // 31579200000
```

## (12) 日付を操作（加算・減算）する

```js
moment("2014-04-01").add('days', 1).format()  // 2014-04-02T00:00:00+09:00  (1日後)
moment("2014-04-01").add('days', -1).format() // 2014-03-31T00:00:00+09:00 (1日前)
// メソッドチェーンで操作可能
moment("2014-04-01").add("M", 1).add("d", 2).format() // 2014-05-03T00:00:00+09:00
```

http://momentjs.com/docs/#/manipulating/



# 公式ドキュメント
http://momentjs.com/docs/

# 参考になったリンク

https://qiita.com/osakanafish/items/5ef636bbcb2c3ef94953
https://qiita.com/taizo/items/3a5505308ca2e303c099
RでVIF統計量を算出しよう！

#VIF統計量とは・・・？
重回帰分析を行なった際に各変数に多重共線性が無いかを調べるための統計量。
各変数の相関係数も多重共線性の指標となりうるが、VIFを調べることによってそのモデルで使用される<b><font color = #ff0000>複数の変数の関係性</font></b>を考慮することができる。

____
#計算してみよう！
##モデルの変数が2つの場合の計算 (モデル　:　a = x + y)
```math

VIF_{xy} = \frac{1}{1-P_{xy}^2}\\
x,y　・・・　各変数\\
P_{xy}　・・・　xとyの相関係数\\

```
と、そこまで難しくない。
____
##モデルの変数が3つ以上の場合の計算  (モデル　:　a = x + y + z + .....)
<font color = #ff0000>ちょっと手計算じゃきついっす・・・</font>

____
###統計ソフト「R」を使う。

+ 「car」パッケージをインストールしよう
Rの「パッケージとデータ」から「パッケージインストーラ」を選んで「car」パッケージをインストールする。「パッケージマネージャ」からcarをロード状態に変更。

____
+ 実際の計算

```vif.R

#重回帰分析の結果をresultに保存
result <- lm(a ~ x + y + z)
#carパッケージを呼び出す
require(car)
#重回帰分析の変数のVIF統計量を算出
vif(result)
# x      y      z
# 1.01  2.05  2.01
#といった感じで結果が表示される
```
____
##数字の見方
VIF統計量は一般的にに10以下であれば多重共線性がないとされる。理想値は2以下である。VIF統計量が10を超えた変数がある場合にはモデルからその変数を外してもう一度VIF統計量を計算するなど、モデルを再構成する必要がある。

以上！
Docker概要1 - 初めの一歩

# はじめに

これから書いていくDocker関連記事の大きな目的は以下の2点です。
社内用に適当に書いた資料ですが何かの役に立つかもしれないのでこちらにも投稿しておこうかなっていう記事です。

* Dockerについての情報を、教育目線でまとめることでDockerに対する理解を深めること。
* 社内のDocker普及を目的として、ざっくりとした概要を社内のドキュメント環境に設置しておくこと。

# 概要

Dockerとはソフトウェアコンテナ内のアプリケーションのデプロイメントを自動化するオープンソースソフトウェアである。
  [Wikipedia](https://ja.wikipedia.org/wiki/Docker)

要するにデプロイの効率化を図るためのソフトウェアと言える？

Linuxカーネルにおける「libcontainer」と呼ばれるLinuxコンテナ技術とaufsのような特殊なファイルシステムを利用してコンテナ型の仮想化を行う。
ようするにlibcontainerでコンテナを生成し、aufsで複数ディレクトリを一つのマウントポイントとしてUnionMountをかけることで仮想環境を実現しているらしい。

## libcontainer

名前空間・cgroup・機能・ファイルシステムへのアクセス管理を持つコンテナを作成
  [http://docs.docker.jp](http://docs.docker.jp/engine/reference/glossary.html#libcontainer)

## aufs (AnotherUnionFS)

aufs (AnotherUnionFS) はもう一つのバージョンの UnionFS、つまり Linux ファイルシステムに対する union mount を実装するファイルシステムサービスである。
  [Wikipedia](https://ja.wikipedia.org/wiki/Aufs)

### union mount

union mounting is a way of combining multiple directories into one that appears to contain their combined contents.
  [Wikipedia](https://en.wikipedia.org/wiki/Union_mount)

# 普通の仮想OSとの違い

VMwareやHyper-Vなどとどのように違うのかざっと書いておきます。

## 仮想OS

コンピュータのリソースを丸ごと仮想的に取り扱う。
仮想マシンへはそれぞれ切り出された仮想ハードウェアを提供され、仮想環境を管理しているHyper-Vなどのアプリケーションがハードウェアリソースの利用を管理する。

http://image.itmedia.co.jp/ait/articles/1701/30/wi-docker01003.png

アプリケーションを実行するためにはまずゲストOSを稼働させなければならず、起動に時間もかかるし、CPUやメモリ、ディスクなどのリソースもOSを稼働させる分多く消費する。

## Docker

Docker上のアプリケーションはホストOS中の1プロセスとして実行されているため、余計なオーバーヘッドがない。
DockerEngineによって、コンテナごとにファイルシステムやネットワークインタフェース、名前空間などが独立している。

http://image.itmedia.co.jp/ait/articles/1701/30/wi-docker01002.png

# Dockerの用語

## Dockerホスト

DockerEngineを搭載した、コンテナを動作させるためのホスト。
VMとかでいうHypervisorみたいなサーバ。

## Dockerイメージ

アプリケーションとその実行環境、展開／操作方法（スクリプト）などをまとめて1つのパッケージにしたもの。
公式に公開されているものもあれば、自作することも出来る。
DockerイメージをDockerEngine上で起動したものがDockerコンテナとなる。

## Dockerfile

イメージに対して適用する指示を記述しておく、一種のスクリプトファイル。
例えばRubyとMySQLのパッケージを追加し、何らかのコマンドを実行する、というようなスクリプトを記述しておく。

Dockerイメージから実際の環境までの差分を記載したファイルになるだろう。

# Dockerイメージと差分管理

上記のようなDockerfileやユーザの作業によって発生した変更は、イメージの差分として保存されており、イメージを直接書き換えることはない。
コレによって同一のイメージから複数のコンテナを生成しつつ、それぞれ異なる処理をさせることが可能となっている。

# 備考

Docker for Windowsは裏でHyper-Vが動いていて、そこでLinux類とDockerEngineが動くことでWindows上にLinuxコンテナが動作するようにみえるらしい。
Haskellで手軽に変数を文字列に埋め込む - 変数展開

# やりたいこと

変数の値を文字列に埋め込みたい！

Haskellで、以下みたいに`++`を使って連結するのは、読みづらいし変更しづらいし嫌ですよね。

```hs
let name = "Jack"
    age  = 10
putStrLn ("Name is " ++ name ++ ". His age is " ++ show age ++ ".")
```

一方、他の言語では、変数を文字列に埋め込む技術が整っています。

Rubyでは、

```rb:hello.rb
name = "Jack"
age  = 23
puts("Name is #{name}. His age is #{age}")
```

JavaScript(ES6?)では、

```js:hello.js
const name = "Jack"
const age  = 23
console.log(`Name is ${name}. His age is ${age}`)
```

Swiftでは、

```swift:hello.swift
let name = "Jack"
let age  = 23
print("Name is \(name). His age is \(age)")
```

Scalaでは、

```scala:hello.scala
val name = "Jack"
val age  = 23
println(s"Name is ${name}. His age is ${age}")
```

PHPでは、

```php:hello.php
<?php
$name = "Jack";
$age  = 23;
print "Name is $name. His age is $age\n";
?>
```

Haskellでもこれら言語と同じ手軽さで変数を埋め込めるライブラリをみつけたので紹介です

# やりかた

[interpolate](https://hackage.haskell.org/package/interpolate)というライブラリを使います。

このライブラリはHaskellの[doctest](https://github.com/sol/doctest)の作者さんの[Simon Hengelさん](https://github.com/sol)製のライブラリのようです。

使い方は簡単で`QuasiQuotes`言語拡張を有効にして、`import Data.String.Interpolate`すれはOKです。

```hs
{-# LANGUAGE QuasiQuotes #-}

import Data.String.Interpolate

main :: IO ()
main = do
  let name = "Jack"
      age  = 23
  putStrLn [i| Name is #{name}. His age is #{age}.|]
```

```:出力
Name is Jack. His age is 23.
```

`[i | ... |]` の中に文字列や変数名を書いていけば展開できます。

`#{}`の中には変数名だけではなく、式を書くことができます。

# 欠点

`TemplateHaskell`を使っているので`Safe`なHaskellにならないことが、ちょっと欠点な気がします。
変数を埋め込むだけで`Safe`でなくなるのはちょっと痛い気がします...
かといって`++`使うのは読みづらく、`Text.Printf`使うとフォーマット指定子が足りなかったり、フォーマットの型の間違いで、実行時エラーでるもの嫌ですよね...
とても便利なので個人的には`Safe`にならなくてもinterpolateを使いたいです。何かいい方法ないですかね〜


# 練習用リポジトリ

以下が実際に使ってみた練習用リポジトリです。

[nwtgck/interpolate-prac-haskell](https://github.com/nwtgck/interpolate-prac-haskell)


# 参考
* https://github.com/sol/interpolate
pythonでAlfred3のworkflowを作ってみた

この記事は [Python Advent Calendar 2017](https://qiita.com/advent-calendar/2017/python_python) 16日目の記事です。

エンジニアは怠惰な人が多いと思いますが、ご多分に漏れず私も怠惰な人間です。
（不労所得で暮らしたい）

そんな怠惰なエンジニアである私は普段からいかに楽して作業をするか常々考えております。
特にキーボードからはなるべく手を離したくない、マウスやトラックパッドは極力使いたいくないという方にはランチャーアプリが欠かせません。
MacのランチャーではAlfredが有名ですね。

# Alfredとは
* Macで使えるランチャーアプリ（Spotlightの強化版みたいなもの）
* アプリの起動、システム操作、ファイル検索、web検索などなど色々な機能が使える

![search@2x.jpg](https://qiita-image-store.s3.amazonaws.com/0/63214/1f934558-518e-0b45-cd1c-58d4cad50408.jpeg)

これまで自分はAlfredをアプリ起動や、スニペットなどで使ってはいたのですが、いまいち有効活用できていない機能がいくつかあるなぁと悶々としていました。
その有効活用できていない機能の代表格が今回お話する「Workflows」です。

# Workflowsとは
* [Alfred powerpack](https://www.alfredapp.com/powerpack/)を購入すると使える機能
* GUIで外部の様々なアプリの処理同士をブロックのようにつなげることで、ひとまとまりのタスクを作成することが可能

![workflows-large@2x.png](https://qiita-image-store.s3.amazonaws.com/0/63214/bf808276-1cbe-e10b-06e8-099f6f953417.png)

パット見難しそうで、自分にはあまり縁のない機能かなぁと思い見てみぬふりをしていたのですが、Advent Calendarを気に実際に触ることを決意しました。

# 環境
* Alfred
* Alfred powerpack
* python（今回のバージョンは2.7.10）

# 作成したWorkflowsの説明

いきなり複雑で難しい機能を作っても使わなかったら意味が無いので、今回は、最近お世話になり始めたタスク管理ツール[Todoist](https://ja.todoist.com/seeYou)へタスクを登録する簡単なWorkflowsを作成しました。

Workflowsの処理単位であるブロックにはスクリプトファイルを指定することも可能です。
ruby, php, shell等様々な言語で記述できるんですが、今回は学習の意味も兼ねてpythonで書くことにしました。
（やっとpythonの話ができた...）


<img width="1212" alt="スクリーンショット 2017-12-16 10.44.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/63214/22338ed7-dd4c-bc6e-02c8-1810155affa8.png">

上は実際のWorkflows作成画面。
処理が簡単なので画面が寂しいですねｗ

左のブロックはは実際にAlfredから入力を受け付ける処理。
右のブロックは受け取った入力をTodoistに登録するpythonスクリプトを指定しています。
実際の処理は以下のとおりです。

```py

import sys
from pytodoist import todoist

class Todoist:
    def __init__(self):
        self.user = todoist.login('id', 'password')

    def add_task_to_inbox(self, task):
        inbox = self.user.get_project('Inbox')
        inbox.add_task(task)
        self.sync()

    def sync(self):
        self.user.sync()  

if __name__ == '__main__':

    if len(sys.argv) != 1:
        sys.stderr.write('Invalid argument\n')
        sys.exit(1)

    query = "{query}"
    argv = query.split(' ')

    todoist = Todoist()
    todoist.add_task_to_inbox(argv[0])
```

Todoistクラスを作り、add_taskを実行しているだけのシンプルなものです。
Todoistは[開発者用のAPIドキュメントページ](https://developer.todoist.com)があり、pythonのライブラリも公開されています。
使用している[pytodoist](https://github.com/Garee/pytodoist)というモジュールは、公式のAPIのラッパーです。

# 実際の使用方法

<img width="674" alt="スクリーンショット 2017-12-16 10.45.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/63214/344d5531-6008-e9b9-549d-d6f103c33112.png">

使用する場合は「todoist 登録したいタスク名」と入力することで、todoistのInboxへタスクが登録されます。


# まとめ・感想
pythonを利用して、Todoistのタスク登録 Alfred workflows を作成しました。
今回のワークフローは機能としてはかなりしょぼいですが、今後自分に欲しい機能を追加していき、いずれ公開したいと思ってます。

また、普段はiOSエンジニアとしてswiftばかり書いているので、あまり書かないpythonに久々に触れるととまどいがありましたｗ
python自体は今後身につけていきたい言語なのでこれからも精進します。
バグ回避策有り：Fall Creator Update (Win10) でpython が 「OSError: raw write() returned invalid length・」

#エラーの状態
Fall Creator Update (Windows10)でcmd.exe や powershell.exeでpythonを実行しているとprint等で以下のようなエラーで止まる場合があります。
OSError: raw write() returned invalid length・・・・
どうも、print文等でOSの認識している文字数とpythonが認識している文字数が違うように認識してエラーを出して止まっているように見えます。

#エラーの情報
以下のように、報告されているようで、puthon3.4以下とpython2.7は保守状態なのでbugf fixしないような事が書かれています。
3.5はパッチは出ているようで、3.6はbugが出ないような対応しているようです。
[Title:	OSError: raw write() returned invalid length on latest Win 10 Consoles](https://bugs.python.org/issue32245)

#エラーの再現スクリプト
実は単純に日本語や英字を表示し続けても止まりません。
実行中のターミナルをクリックしたりとどうも表示中に別のイベントが発生すると止まりやすいようなので、以下のようなスクリプトでエラーが出るのを確認します。（winsock等の通信スクリプとかでも止まりやすくなります）

```python:test.py
import string,random

def random_string(length, seq=string.digits + string.ascii_lowercase):
        sr = random.SystemRandom()
        return ''.join([sr.choice(seq) for i in range(length)])

while(True):
  print(random_string(100))

```

上記スクリプトをwindows10のコマンドプロンプト(cmd.exe)から
python test.py
と実行するとランダムな文字列が表示され続けますが、この表示されているウインドウで左クリックしてから、右クリックとかすると以下のようなエラーで止まる事が確認出来ます。(python3.4で確認）

---
k83kr1k658q9pf75hlrgpqvrlqb6h8u1v9pnum03o4baw7jm6bj7ii8y70wcmv6ndfiq1cxrmi8hyhij0ndguh60ue1er3rb9inw
k83kr1k658q9pf75hlrgpqvrlqb6h8u1v9pnum03o4baw7jm6bj7ii8y70wcmv6ndfiq1cxrmi8hyhij0ndguh60ue1er3rb9inw
Traceback (most recent call last):
  File "test.py", line 9, in <module>
    print(random_string(100))
OSError: raw write() returned invalid length 204 (should have been between 0 and 102)

---

#エラーの回避策
1. python3.5はパッチを当てる？python3.6は対応済のようなのでpython3.5かpython3.6に移行する方法があります(未検証なので、python.orgに書かれている事が正しければです）
2. 1.以外ののversionの場合最初に以下のような記述を追加すればエラーは回避出来るようです。

---
import win_unicode_console
win_unicode_console.enable()

---

これは上記エラー再現スクリプトの先頭に追加してエラーが出ない事を確認しています(python3.4　他のversionは未検証です）

ただこの方法だと全てのスクリプトに追加しなければならないのですが、pythonは立ち上げ時にsitecustomize.pyを読み込むようなので、これに追加（なければ新規作成）すればよさそうです。以下の概要があります。
[29.13. site — サイト固有の設定フック](https://docs.python.jp/3/library/site.html)
この真ん中位の所で書いてあります。
sitecustomize.pyがあるかどうかの確認はpythonをインタープリターモードで立ち上げて
import sitecustomize
でエラーが無ければ既にあって、そのパスは
sitecustomize.\_\_file\_\_
を見ればファイルのパスはわかります。

新規作成の場合は適当にインストールしたライブラリを読み込んで
import numpy
numpy.\_\_file\_\_
とかすれば、site-packagesのパスがわかるので、
...lib\site-packages\sitecustomize.py
に作成すればOKです。
Licodeを使ってみた

# はじめに

この投稿は[2017年WebRTCアドベントカレンダー](https://qiita.com/advent-calendar/2017/webrtc)の17日目の記事です。

WebRTC SFU/MCUの「Licode」を使ってみました。
記事公開時点では、日本語の情報はほとんどないようです。

# 実行環境

* Ubuntu 14.04 LTS
* ConoHa メモリ 2GB/CPU 3Coreプラン

# Licode動作環境

* Ubuntu 14.04
* MacOS X 10.11以上

# インストール

* ドキュメントに従えばインストールできます。
* 操作はすべてrootで行いました。

## Githubからクローン

```shell
git clone https://github.com/lynckia/licode.git
cd licode
```

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

```shell
./scripts/installUbuntuDeps.sh
```

## Licodeのインストール

```shell
./scripts/installNuve.sh
./scripts/installErizo.sh
```

## サンプルのインストール

```shell
./scripts/installBasicExample.sh
```

## Licodeの起動

* screenコマンドを使うか、もう一つssh接続するなどして、サンプルも起動できるようにしてください。

```shell
./scripts/initLicode.sh
```

## サンプルの起動

* サンプルはHTTPなので、メディアの取得ができません。
* 自己証明書を作成するかSSHポートフォワーディングを使用してください。
* 私は、ポートフォワーディングを使いました。サーバーの3001番ポートをlocalhostの3001に転送するように設定してください。

```shell
./scripts/initBasicExample.sh
```

# サンプル実行

1. [http://localhost:3001](http://localhost:3001)にアクセスしてください。(ポート転送を設定した場合)
2. 「Test Connection」ボタンをクリックしてください。
3. メディアへのアクセス許可を求めるダイアログが表示されるので、許可してください。
4. ブラウザの画面に取得した映像と一旦サーバーに送られた映像が表示されます。

# 結果

* 上記の内容でサンプルを動かした場合です。

* 帯域
    * 送信:約500kbps
    * 受信:約500kbps
* サーバー側CPU使用率
    * 約30%

# まとめ

ビルドに結構時間がかかりました。
依存パッケージにはrabbitmqやmongodbがあり、これらのインストールに時間がかかっているものと思われます。
また、ドキュメントが少ないと思いました。
個人的にはJanusの方が使いやすいと思いました。
VirtualBox で ホスト側 Windows の共有フォルダにアクセスできない→ファイアウォールの設定が必要


# 手順
コマンドプロンプト >> control[Enter] >> システムとセキュリティ >> Windows Defender ファイアウォール >> Windows Defender ファイアウォールを介したアプリまたは機能を許可 >> ファイルとプリンターの共有のパブリックにチェック >> [OK]

# 環境
- Windows 10 Pro 64-bit Build 16299
- VirtualBox 5.2.2 r119230 (Qt5.6.2)
- Ubuntu 16.04
- Ubuntu 17.10


# おまけ
通らなかった ping もこれで通るようになった。
非同期のデータ取得処理をカプセル化する

以下のような状況を想定しています。
1. 非同期でデータ取得をしたい
2. 取得したデータに前処理をしてから使用したい
3. 無駄な処理をしないように初回の結果を保存しておきたい
4. 呼び出す側はそれを考えなくても使えるようにしたい

```javascript:getDataClosure.js
/**
 * 非同期のデータ取得処理
 */
const rawData = Promise.resolve("1,2,3");

/**
 * 前処理
 * @param {*} rawData 
 */
const preprocessing = (rawData) => {
    return rawData.split(",");
};

/**
 * データを取得するクロージャを返す
 * @param {*} rawData 元データ
 * @param {*} preprocessing 前処理をする関数
 */
const getDataClosure = (rawData, preprocessing) => {
    let data;
    return () => {
        console.log('get start');
        if (typeof data === "undefined") {
            // 前処理をする
            return rawData.then((rawData) => {
                console.log('preprocessing');
                data = preprocessing(rawData);
                console.log('get end');
                return data;
            });
        } else {
            // 前処理済だったらそれを返す
            console.log('get end');
            return Promise.resolve(data);
        }
    }
}

// 使用する
const dataClosure = getDataClosure(rawData, preprocessing);
const displayData = () => {
    dataClosure().then((data) => {
        console.log(data);
    });
}

displayData();
setTimeout(displayData, 1000);
setTimeout(displayData, 2000);

```

実行結果

```
get start            <- 初回の取得処理
preprocessing        <- 初回なので前処理をする
get end              
[ '1', '2', '3' ]    <- 初回の取得結果
get start            
get end              <- ２回目は前処理をしていない
[ '1', '2', '3' ]    <- 同じ結果が返ってくる
get start            
get end              
[ '1', '2', '3' ]    <- ３回目も同様
```

上記の欠点

* 初回の処理が終わる前に２回目以降を呼び出すと前処理が動いてしまう

```
displayData();
displayData();
displayData();
```

```
get start
get start
get start
preprocessing
get end
preprocessing
get end
preprocessing
get end
[ '1', '2', '3' ]
[ '1', '2', '3' ]
[ '1', '2', '3' ]
```

もっといい書き方があるのだろうか。
コードレビューに役立つ React Storybook の閲覧環境を作る

本エントリでは、CircleCI と Storybook を組み合わせて、GitHub のプルリクエストから簡単に Storybook を表示する方法を紹介します。

# はじめに

[Storybook](https://storybook.js.org/) は React をコンポーネント単位で開発することができる開発環境です[^1]。

私の会社でも少し前から導入しているのですが、コードレビューの時に GitHub 上から Storybook が開けたらなあと思うことがありました。
やりかたは色々あると思いますが、今回は CircleCI を使って、手軽に Storybook を閲覧できる環境をつくる方法を紹介します。

説明は良いからサンプルが欲しい！という人は、
[リポジトリ](https://github.com/yszk0123/storybook-code-review-example)を用意したのでご覧ください。

# 手順

さっそく導入方法に入りますが、Storybook が既に build-storybook という便利な機能を用意してくれているので、特別難しいことはありません。
以下のような手順になります。

1. GitHub に push
2. CircleCI でテストを実行
3. build-storybook コマンドで Storybook の静的ファイルを作成し、Build artifacts フォルダに保存
4. 生成された html ファイルへのリンクを GitHub のプルリクエストコメントとして投稿
5. レビュアーがリンクから Storybook を開く

# 導入

今回、コンポーネントに変更がない場合は、Storybook の生成をスキップするようにしました。

以下、storybook の導入は終わっていると仮定して、重要な部分のみ説明します。
途中に出てくる `GITHUB_API_TOKEN` は GitHub の API トークンを入れた環境変数です。プルリクエストにコメントを POST できる権限を与えたトークンを CircleCI の設定画面で登録しておいてください。

まず、build-storybook コマンドを npm コマンドで使えるようにしておきます。

```json:package.json
{
  ...
  "scripts": {
    "build-storybook": "build-storybook -c .storybook"
  },
  ...
}
```

メインとなる処理。やや長いので設定ファイルから分離しています。
条件判定が大雑把なのはご了承ください。

```bash:scripts/build-storybook-for-code-review.sh
#!/bin/bash
set -eu

# コンポーネントに変更がなければスキップ
if git diff master...HEAD --name-only | grep -q "src/\|stories/" ; then
  :
else
  echo "[Storybook] Skip"
  exit 0
fi

# プルリクエストが作られていなければスキップ
PULL_REQUEST_ID="${CI_PULL_REQUEST##*/pull/}"
if [ -z "$PULL_REQUEST_ID" ]; then
  echo "[Storybook] Skip"
  exit 0
fi

# 静的ファイルを作り build artifacts として保存
npm run build-storybook
mkdir -p "$CIRCLE_ARTIFACTS/storybook/"
mv storybook-static "$CIRCLE_ARTIFACTS"

# GitHub のプルリクエストにリンクを付けてコメントを投稿
STORYBOOK_URL="$CIRCLE_BUILD_URL/artifacts/$CIRCLE_NODE_INDEX/$CIRCLE_ARTIFACTS/storybook-static/index.html"
curl -X POST \
     -H "Authorization: bearer $GITHUB_API_TOKEN" \
     -H "Accept: application/vnd.github.v3.html+json" \
     -d "{\"body\":\"[Storybook] Created ([view stories]($STORYBOOK_URL))\"}" \
     "https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/issues/$PULL_REQUEST_ID/comments"
```

CircleCI 設定例を載せておきます。
以下は 1.0 の設定ですが、少し修正すれば 2.0 でも使えるはず。。

```yaml:circle.yml
machine:
  node:
    version: 8.9.3
deployment:
  development:
    branch: /feature\/.*/
    commands:
      - ./scripts/build-storybook-for-code-review.sh
```

# 実行例

<img width="794" alt="Screen Shot 2017-12-16 at 10.55.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/89649/b918cc06-196e-7186-79d6-a2b6aa1666b4.png">
図1: GitHub

<img width="780" alt="Screen Shot 2017-12-16 at 10.57.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/89649/112dbff6-f2ab-ae05-cd73-d1788ca50603.png">
図2: Storybook

# おわりに

iframe などで Storybook の画面を埋め込めるとさらに便利かもしれませんが、そこそこ快適になりました。
現状、プルリクエストを作ってから CircleCI が実行されないと、コメントが投稿されないという問題があるので、そのうち直したいです。

[Travis CI](https://docs.travis-ci.com/user/uploading-artifacts/) でも同様の環境を作ることはできますが、AWS S3 のバケットを自分で用意しておく必要がありそうです。

[^1]: 最近は Vue.js にも対応したようです。
人にものを教えるのって難しい・・・

どうも、sasa0です。

この記事は『Jisibari Advent Calendar 2017』1日目の記事の記事です。

２週遅れで頑張っていきます。

スーパーポエムかつ答えの出ていない悲しみの「ぼやき」なので、
**忙しい方は読んではいけません！**

では、はじめていきます。




## 人にものを教えるのって難しい

プログラミングは、人に教えたり（教わったり）することが多い分野だと思います。
その中で僕がよく感じることが、
**「あれっ・・・ピンとくる説明ができない・・・」**
というあの不思議な感覚です。

この感覚は、
僕だけのものではなく、皆さん感じたことがあるものだと思います。

「なぜ説明することができないのだろう・・・」
と考えた結果をさっくりとまとめていきたいと思います。

## りんごはオレンジじゃない
例えば、赤ちゃんがいます。
赤ちゃんは無知です。
りんごを知りません。

![apple-2788616_640.jpg](https://qiita-image-store.s3.amazonaws.com/0/120255/9ce3cde9-1de7-a2bf-87fc-1791a0f9c282.jpeg)

あなたは、その赤ちゃんにこの画像を見せて、
「これはりんごだよ！」
と教えてあげます。

赤ちゃんは
「ふむふむ、これがりんごか！」
と思うでしょう。


赤ちゃんは無知です。
やはりオレンジも知りません。
心優しいあなたはオレンジの画像も見せてあげます。
![orange-1117645_640.jpg](https://qiita-image-store.s3.amazonaws.com/0/120255/5f527f8f-e6a5-6896-2263-69058d131ef2.jpeg)




**ここからが難しいです！**

この時は赤ちゃんは
**「おっ、りんごじゃん！」**
と思ってしまうかもしれないのです!!


なぜなら、りんごとオレンジはそっくりだからです。

「いやいや！全然似てないでしょ！色も違うでしょ！」
と思う方もいらっしゃると思いますが、

実は似ていて、
両方とも『緑の葉っぱがついている木になっている丸いもの』という共通の特徴があるのです。

もし、赤ちゃんがりんごの画像を見たときに
「あーこんな感じの緑の葉っぱがついている木になっている丸いものってりんごっていうのか〜」
と思ってしまった場合、
オレンジを見せたとしても「りんごだりんごだ！！」となってしまうでしょう。
りんごという言葉を「緑の葉っぱがついている木になっている丸いもの」の総称として覚えてしまうのです。
この誤解を解くは
「これはオレンジで、りんごとは違うものだよ！」と教えてあげる必要があるのです。

つまり、何か（A）を教えるにはBCDE.....を教えてあげて、他との差別化をすることでようやくAを理解することができるのです。

### もっと具体性をあげたらいいじゃない！
Aの説明を具体的にして、Aの説明だけで差別化するという方法もありますが、こちらも難しいです。
wikipediaで詳しく見ましょう。

>リンゴ（林檎、学名：Malus pumila）は、バラ科リンゴ属の落葉高木樹。またはその果実のこと。植物学上はセイヨウリンゴと呼ぶ。春、白または薄紅の花が咲く。果実は球形で甘酸っぱい。
[https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%B3%E3%82%B4](https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%B3%E3%82%B4)

この説明はおそらく正しくて、りんごをピンポイントでさしているのでしょう。
しかし、りんごを知らない人にこの説明をしたところで僕らが知っているりんごを想像できるとは到底思えません。

具体性をあげると理解することが難しくなってしまうのです。


## 概念の説明はもっと難しい。
画像は素晴らしいです。
ピンポイントでそのものを表示して伝えることができます。

しかし、概念は実体がないので画像で説明することがとても難しいです。

プログラミングをやっているとこういった実体のない概念の説明をする必要がある場合が多いです。

その場合よく使われる手法が、
**「身近なもので例える」**
というものです。

僕はプログラミングをRubyで勉強を始めました。
Rubyはオブジェクト指向の言語です。
その中でClassの説明でよく見かけるのが
「Classという設計図を元に車というオブジェクトを作成するようなもの！」
などなどです。

- 設計図
- 車

などの身近な例で説明していて、シンプルでとてもわかりやすいです。

しかし、実際Rubyを触っていて、それらの説明を思い返すと「う〜ん・・・」となることが多いです。

身近なもので例えるという技は、
「オブジェクト指向におけるClass」
「設計図と車」
というところに共通項を見出し、抽出するという高度な技です。

これは説明している側の人間はとても気持ちがいいです。
「なんてわかりやすいんだ・・・やっぱり俺って天才だな！」
と悦に入ります。

しかし、説明されている側は
わかったような？わかっていないような？不思議な感覚になってしまいます。腑に落ちないのです。

なぜでしょう？

それは、抽象性が高いからです。
抽象性が高くなればなるほど、理解することが簡単になります。
（具体性が高くなればなるほど、理解することが難しくなるのと逆ですね）

しかし、抽象性をあげすぎると現実と乖離してしまい、「説明してもらっている概念」と「身近な例」を紐づけて考えることができなくなってしまうのです。
プログラミングは思考の塊で実体が掴みづらいので、ある意味現実と乖離していると言えます。
その「プログラミング」と「設計図と車」という大きく距離の開いたものを繋ごうとすると抽象性も大きくなってしまうのです。
距離の大きさは抽象性の大きさです。
(エンジニアはしばしば浮世離れした連中が多いと言われていますが、それはプログラミングという現実と乖離したことをしているせいでそうなってしまうのだと僕は思います。)

しかも、頭が良い人ほど距離が大きく開いたものから共通項をみつけるのが得意です。
およそ共通項など見つかるはずもない距離ものから、共通項を見出します。
そして誰も腑に落ちないということが多いです。


## 最後にまとめ

- 具体性が高いと理解できない。
- 抽象性が高いと理解できても腑に落ちない。

具体性と抽象性のバランスが取れた時に美しい説明になるのです。

やっぱり人に教えるのは難しいですが、頑張って行くしかないですね！
Google Chrome > Ubuntu 16.04 LTS > update > sudo dpkg -i google-chrome-stable_current_amd64.deb

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
```

Google Chromeの動作が遅い。

- Qiitaで下書きをすると、プレビューの更新が遅い
    - 修正一つ前のもので表示される
    - 改行入力などの追加修正が必要
- mindmup.comで操作が重い

Youtubeで音楽（＋映像）を流しているのが原因だろうか。

Google Chromeのセキュリティアップデートが来ていたので適用した。

コマンドは下記で実行した。Google Chromeが起動中でも適用でき、Chrome再起動後に適用バージョンであることを確認した。

```
sudo dpkg -i google-chrome-stable_current_amd64.deb
```

いーあるふぁんくらぶ

Chromeのupdate後、上記のほとんどの問題は解消した。
(解消しないのはxxx)
各ミドルウェアのIPv6対応状況


# Apache
既に対応済みです。

#### Listen ディレクティブでの設定方法

`Listen *:80`

このように書けば問題ありませんが、特定のIPv6アドレスでリッスンしたい場合は以下のように書きます。

`Listen [2001:db8::a00:20ff:fea7:ccea]:80`

この括弧は、[RFC3386](https://tools.ietf.org/html/rfc3986)で規定されています。
IPv6は今までと違い、セパレータに`:`を使います。
この為ホスト名とIPアドレスを区別するためURIでは括弧をつけるように規定されています。

# Nginx
既に対応済みです。

#### Listen ディレクティブでの設定方法
Apache の場合と殆ど変わりません。
ただし、リッスンアドレスを不特定にする場合、Apacheでは`*`を利用しますがNginxでは`[::]`を利用するので注意が必要です。

`listen [::]:80;`
`listen [2001:db8::a00:20ff:fea7:ccea]:80;`

またIPv4と併せて利用する場合、Apacheと違い両方書く必要があります。

`listen 80;`
`listen [::]:80;`


# sshd
既に対応済みです。

#### ListenAddress ディレクティブでの設定方法

`ListenAddress ::`

この場合も、特定のIPv6アドレスでリッスンしたい場合は、以下のように書く必要があります。

`ListenAddress [2001:db8::a00:20ff:fea7:ccea]`

また、リッスンポートを変更する場合（例としてポート番号222の場合）は、以下のように書きます。

`ListenAddress [2001:db8::a00:20ff:fea7:ccea]:222`

IPv4と併せて利用する場合は、Nginxと同様に両方書く必要があります。

`ListenAddress 0.0.0.0`
`ListenAddress ::`
CloudFormation のテンプレートを書くときに参考にするページメモ（随時更新）

[AWS CloudFormationによるVPC作成 + public及びprivateサブネット作成](https://qiita.com/na0AaooQ/items/251790a7ef311804b77e)

[AWS::EC2::Instance](http://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html)
Reaper 5 スクリプト管理ツール 「ReaPack」 を使ってみた

# はじめに

**カスタマイズする Daw Reaper** / 
ReaPack はReaper職人にとって **必須ツール** といってもよいかもしれないレベル。

# ReaPack をインストールしてみた

ReaPackのインストールファイルは公式サイトからダウンロードできるので、ダウンロードしてきます。

**ReaPack 公式サイト**
**ReaPack Package manager for REAPER** : ( http://reapack.com/ )

次に、Reaper の リソースパス[^1] 内の **UserPlugin** フォルダの中に **reaper_reapack** をコピー。
これで次回、Reaper起動時にReapack が読み込まれ使えるようになります。



![01_Install_X.png](https://qiita-image-store.s3.amazonaws.com/0/212250/400dc42a-43a2-eb8d-b46f-1d195185a713.png)

Reaper公式のYouTuber "Reaper Blog" で解説している動画は下記に(ただし、英文)

* **Reaper Blog** :[How To Use the new Reapack Extenstion for Reaper](http://reaperblog.net/2016/06/how-to-use-the-new-reapack-extension-for-reaper/)
* **Reaper Blog** :[ReaScript ReaPack Tips](http://reaperblog.net/2016/06/reascript-reapack-tips/ )



![02_ReaPack_Normal.PNG](https://qiita-image-store.s3.amazonaws.com/0/212250/557998c8-1242-fc1f-834d-a2e183d07d83.png)

画像上 : インストールを終えて最初に起動したところ。

Reapackは 各スクリプト制作者の **リポジトリURL(更新情報URL)** を登録して  一括して最新版のチェックやスクリプトのインストールを行っているようです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/212250/28834d6f-7906-ebc2-9650-8f744597bd11.png" width="650px" />

画像上 : 標準で登録されている **ReaTeam** リポジトリに収録されてあるスクリプト一覧。

# リポジトリURLを追加してみた

主なリポジトリURL以外は ReaPack公式の **Repository list** ページで確認できます。 Reaper 公式のForumにリポジトリURLをポストしている方もいるようです。

**ReaPack** :[Repository list](https://reapack.com/repos) ( https://reapack.com/repos )

![04_ImportRepository_x.png](https://qiita-image-store.s3.amazonaws.com/0/212250/fd9bc781-5db9-c917-0f50-2747b5b94a2b.png)

画像上 :  **Repository list** から リポジトリURLを追加しているところ。

<img src="https://qiita-image-store.s3.amazonaws.com/0/212250/fc690648-8404-1b92-69b2-c0af027999cd.png" width="650px" />

画像上 :  **ReaPack Package Browser** 画面でインストール済、登録したリポジトリに収録されてあるスクリプトを確認しているところ

**ノート :**
 ReaPackを使うと **スクリプトの海** になる という名言がある。

非常に数がある一方で、限定的な機能のスクリプト、特殊なスクリプトも紛れており、結果的に普段使わないスクリプトが増えていくことに少なからず繋がります。 ( 欲しかった機能をスクリプトで追加することができても、実行するまでに探すひと手間が増えていく。)

しっかり迷子にならないように吟味してインストールするのがおすすめ。(といっても、スクリプトの数が増えても、今のところ動作に支障はないようです。)

* 自分の使いたい機能のみを選別してインストールする。
* よく使う機能だけをキーボードショートカットに登録する。
* 作業の中で直感とシンプルさは大事にしたい

# 結び

あまり表舞台に出てこないReaperですが、開発者はかつてのオーディオプレイヤーwinampの制作者であり、現在も少数精鋭のチームでReaper Forum ユーザーのレスポンスを受け取りながら開発、アップデートを行っています。( 1週間~2週間のペースで 開発版 をforumで公開しているようです。)

**1行でわかるまとめ :**
拡張スクリプトをインストールする時、**ReaPack** を使うと超便利で楽。

# 参考

* **Reaper Official** : ( https://www.reaper.fm/)
* [Reaper Official Forums] (https://forum.cockos.com/forumdisplay.php?f=20)
* **ReaPack** Package manager for REAPER : ( http://reapack.com/ )
* **ReaPack** Repository List : ( https://reapack.com/repos)
* **AdmiralBumbleBee.com** : [Reaper Script Showcase ](http://www.admiralbumblebee.com/ReaperScripts.html)


[^1]: **Reaper リソースパスの確認方法** : [ reaper の 上部メニューの ``` Options ->  Show REAPER resource path n explorer/finder.``` から確認することができます。]
self.classの形でクラスメソッドを呼び出すときの注意点


## はじめに

この記事は書籍「[プロを目指す人のためのRuby入門](http://gihyo.jp/book/2017/978-4-7741-9397-7)」に掲載できなかったトピックを著者自らが紹介するアドベントカレンダーの18日目です。
本文に出てくる章番号や項番号は書籍の中で使われている番号です。

今回は`self.class`でクラスメソッドを呼び出すときの注意点を説明します。

### 必要な前提知識

「プロを目指す人のためのRuby入門」の第7章まで読み終わっていること。

## self.classの形でクラスメソッドを呼び出すときの注意点

7.5.3項ではクラスメソッドをインスタンスメソッドから呼び出す場合、次のように「self.class.クラスメソッド名」のような形で呼び出せることを説明しました。

```ruby
class Product
  attr_reader :name, :price

  def initialize(name, price)
    @name = name
    @price = price
  end

  # 金額を整形するクラスメソッド
  def self.format_price(price)
    "#{price}円"
  end

  def to_s
    # self.class.クラスメソッド名の形でクラスメソッドを呼び出す
    formatted_price = self.class.format_price(price)
    "name: #{name}, price: #{formatted_price}"
  end
end
```


ただし、サブクラスでも同じ名前のクラスメソッドを定義した場合は、`self.class`だと思いがけない結果になることがあるので注意が必要です。

以下のコードではProductクラスのサブクラスであるDVDクラスで、`format_price`という同じ名前のクラスメソッドを定義したときの実行例です。

```ruby
class Product
  # 省略

  def self.format_price(price)
    "#{price}円"
  end

  def to_s
    # self.classが返すクラスに注意！
    formatted_price = self.class.format_price(price)
    "title: #{title}, price: #{formatted_price}"
  end
end

class DVD < Product
  # 親クラスと同名のクラスメソッドを定義する
  def self.format_price(price)
    "#{price}ドル"
  end
end

product = Product.new('A great movie', 1000)
# 円で表示される
product.to_s #=> "title: A great movie, price: 1000円"

dvd = DVD.new('An awesome movie', 3000)
# ドルで表示される
dvd.to_s     #=> "title: An awesome movie, price: 3000ドル"
```

ご覧のとおり、ProductとDVDで表示される文字列が異なりました。この理由は次の通りです。

`self.class.format_price`と書いた場合、`self.class`の返す値はオブジェクトによって異なります。Productクラスのオブジェクトであれば`Product`が返りますが、DVDクラスのオブジェクトであれば`DVD`が返ります。そのため、`Product`クラスの`format_price`が呼ばれたり、`DVD`クラスの`format_price`が呼ばれたりするのです。その結果としてProductは「円」で表示され、DVDは「ドル」で表示されました。

一方、次のように具体的なクラス名を書いていた場合は常に`Product`クラスの`format_price`メソッドが呼ばれるので、DVDも「円」で表示されるようになります。

```ruby
def to_s
  # クラス名をベタ書きしたので、DVDクラスのformat_priceが呼ばれることはない
  formatted_price = Product.format_price(price)
  "title: #{title}, price: #{formatted_price}"
end
```

親クラスとサブクラスで同じ結果になるべきか、異なる結果になるべきかは要件によって変わってくるので、一概にどちらが正解ということはできません。ただし、一般論としてインスタンスメソッドに比べるとクラスメソッドは継承の機能を積極的に活用するケースは少ないと思います。どちらかというと、「偶然同じメソッド名を定義してしまった」というケースの方が多いのではないでしょうか。もしそうであれば、`self.class`と書いて結果が変わるのは不具合になってしまいます。というわけで、「どっちを選んでもよい」という状況なのであれば、`Product.format_price`のように具体的なクラス名を書いてクラスメソッドを呼び出す方が、より安全かもしれません。

## 次回予告

次回はStructクラスの使い方を紹介します。
QiitaのMarkdownでTex数式を書くときは半角円記号でなくバックスラッシュを使う

Qiitaで記事書くときに、Texで数式書けるとのことなので、試してみたときにちょっとはまったことをメモします。

[Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)や[Qiitaの数式チートシート](https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada)を見ると、Tex記法でQiita上に美しく数式を記述できるとあります。

早速試してみようと、分数の引き算の数式を書いてみるわけですが、以下のようにうまくいきません。

記述内容

> \`\`\`math
> ¥frac{1}{2} - ¥frac{1}{3} = ¥frac{1}{6}
> \`\`\`

結果

```math
¥frac{1}{2} - ¥frac{1}{3} = ¥frac{1}{6}
```

全然美しくない。。。分数表記にならない。。。なぜだ！？


で、いろいろ悩んだり試したりしたんですが、結論を言うと、バックスラッシュ「\」を書くべきところでは、半角円記号「¥」ではだめで、本当にバックスラッシュ記号を書く必要がありました。


記述内容

> \`\`\`math
> \frac{1}{2} - \frac{1}{3} = \frac{1}{6}
> \`\`\`

結果

```math
\frac{1}{2} - \frac{1}{3} = \frac{1}{6}
```

日本語環境のキーボードではバックスラッシュが直接入力できず、すべて半角円記号になるので、これは罠ですね。  
とりあえず、原稿を書くときは半角円記号で書いておいて、あとでまとめて置換するしかないでしょうか。うーむ、手間がかかる。

## 追記

alt/optionキーを押しながら円記号キーを押すことで、バックスラッシュが直接入力可能でした。
PlanetMeronさん、情報提供ありがとうございました！
Python > subprocess > /dev/nullに出力する > Popen()の引数にstdout=sb.DEVNULL

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
```

数千ケースの処理を行う場合、それぞれのコマンド出力(stdout)は/dev/nullに設定したい。

https://docs.python.jp/3/library/subprocess.html
> subprocess.DEVNULL(原文)
Popen の stdin, stdout, stderr 引数に渡して、標準入出力を os.devnull から入出力するように指定するための特殊値です。

使ってみた。

### code

```test_subprocess_devnull_171216.py
import subprocess as sb
import time

cmd = "echo Are you listening me?"

# 1.
sb.Popen(cmd.split())
print("I'm all ears.")

time.sleep(1)  # msec
print("---")

# 2.
sb.Popen(cmd.split(), stdout=sb.DEVNULL)
print("I'm talking to myself.")

```

```txt:run
$ python3 test_subprocess_devnull_171216.py 
I'm all ears.
Are you listening me?
---
I'm talking to myself.
```

### 結果について

- 1.のPopen()のstdoutは表示される [正常]
- 2.のPopen()のstdoutは表示されない [正常]

'Are you listening me?'が'I'm all ears.'(しっかり聞いてますよ)の後に出力される。
これらのタイミングについては未消化。MIT(Most Important Task)が終わってから調べるかもしれない。
privateメソッドをレシーバ付きで呼び出せるケース

**(2022.6.4追記)**
以下の情報はRuby 2.4時代の情報である点にご注意ください。
Ruby 2.7以降ではふつうのprivateメソッドもself付きで呼べるようになるなど、最新のRubyでは仕様が若干変わっています。

https://qiita.com/jnchito/items/aa4ebf6f0e363a1b8098#self%E3%82%92%E4%BB%98%E3%81%91%E3%81%A6private%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%8C%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%9B%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F772

なお、拙著「プロを目指す人のためのRuby入門 改訂2版」ではRuby 3.0に対応して、こうした新しい言語仕様についても詳しく説明しています。こちらもぜひご覧ください。

https://gihyo.jp/book/2021/978-4-297-12437-3

## はじめに

この記事は書籍「[プロを目指す人のためのRuby入門](http://gihyo.jp/book/2017/978-4-7741-9397-7)」に掲載できなかったトピックを著者自らが紹介するアドベントカレンダーの17日目です。
本文に出てくる章番号や項番号は書籍の中で使われている番号です。

今回はprivateメソッドをレシーバ付きで呼び出せるケースを説明します。

### 必要な前提知識

「プロを目指す人のためのRuby入門」の第7章まで読み終わっていること。

## privateメソッドをレシーバ付きで呼び出せるケース

7.7.2項でも説明したとおり、Rubyのprivateメソッドは`self`キーワードを付けて呼び出すことができません。

```ruby
class User
  def hello
    # nameメソッドはprivateなのでselfを付けるとエラーになる
    "Hello, I am #{self.name}."
  end

  private

  def name
    'Alice'
  end
end
user = User.new
user.hello #=> NoMethodError: private method `name' called for #<User:0x007fb18a3903d0>
```

一方、7.5.1項では`name=`のようなセッターメソッドを呼び出すときは必ず`self`を付ける必要があると説明しました。

```ruby
class User
  attr_accessor :name
  
  def rename_to_bob
    # メソッド内でセッターメソッドを呼び出す場合はselfを必ず付ける
    self.name = 'Bob'
    
    # selfを付けないとローカル変数への代入と見なされる
    name = 'Carol'
  end
end
```

では、もしもセッターメソッドがprivateメソッドだったらどうなるんでしょうか？セッターメソッドは`self`を付けて呼び出す必要がありますし、privateメソッドは`self`を付けて呼び出すことができません。完全に矛盾してしまいます。

```ruby
class User
  attr_accessor :name 
  # セッターメソッドのみprivateにする
  private :name=
  
  def rename_to_bob
    # name=を呼び出したいが、privateメソッドなのでselfを付けられない？
    self.name = 'Bob'
  end
end
```

うーん、これは困りました・・・と思いきや、実はセッターメソッドの場合はprivateメソッドでも`self`付きで呼び出すことができます。

```ruby
class User
  attr_accessor :name 
  # セッターメソッドのみprivateにする
  private :name=
  
  def rename_to_bob
    # セッターメソッドなら公開レベルにかかわらずself付きで呼び出せる
    self.name = 'Bob'
  end
end

user = User.new
# エラーにならずにnameを変更できる
user.rename_to_bob
user.name #=> "Bob"
```

もちろん、`name=`はprivateメソッドなのでクラスの外部からは呼び出すことができません。

```ruby
user.name = "Carol"
#=> NoMethodError: private method `name=' called for #<User:0x00007fdb78827138 @name="Bob">
```

ただ、このようなコードは混乱を招きやすいので、何か特別な理由がなければセッターメソッドを使わずにインスタンス変数を直接書き換える方がよいでしょう。

```ruby
class User
  # ゲッターメソッドのみ用意して、セッターメソッドは作らない
  attr_reader :name 
  
  def rename_to_bob
    # インスタンス変数を直接書き換える
    @name = 'Bob'
  end
end

user = User.new
user.rename_to_bob
user.name #=> "Bob"
```

### 参考

privateなセッターメソッドがself付きで呼べるようになったのはRuby 1.8からみたいです。

https://docs.ruby-lang.org/en/2.4.0/ChangeLog-1_8_0.html

> parse.y (attrset)
> “self.foo=x” can be legal even when “foo=” is private.

## 次回予告

次回は`self.class`でクラスメソッドを呼び出すときの注意点を説明します。