OmniAICreator/Qiita-1.07M huggingface dataset:
Slackの外部Apps(Integrations)の場所・管理

# はじめに

Slackをフリープランで運用していると連携できるアプリの制限にひっかかると思います。
このサービス・Integrationsが10個までの制限のため管理画面にたまに行きたくなるのですが、いつも迷子になるので投稿しておきます。

# 場所とスクリーンショット

| URL | https://your_team_name.slack.com/apps/manage |
|:-:|:-:|
|任意値|your_team_name|

この画面が出てきたら正解。

![スクリーンショット 2017-06-13 17.26.05.png](https://qiita-image-store.s3.amazonaws.com/0/112929/516ed969-bb35-6f7a-bb16-9e72b03da549.png)

# 探し方
Web版Slackからの道筋を覚えるのがいいと思います。

![スクリーンショット 2017-06-13 17.19.50.png](https://qiita-image-store.s3.amazonaws.com/0/112929/417fa30d-fe06-2fa4-ac64-e976f5093681.png)

名前横の`∨`と`Apps & Custom Integrations`をポチ

![スクリーンショット 2017-06-13 17.24.38.png](https://qiita-image-store.s3.amazonaws.com/0/112929/2bd52fe0-fe6d-22de-2964-6a7672b4ad0f.png)

`Manage`をポチで出てきます。

# 外部サービスの追加

どちらからでも探せます。
https://your_team_name.slack.com/apps/
https://your_team_name.slack.com/apps/manage












.
.NET Framework (NuGETのExifLib) を使用して写真撮影位置(GPS情報)を得る

#はじめに
.NET Frameworkの NuGet パッケージでは、EXIF を扱うものがいくつかありますが、このうち評判が高そうな（ダウンロード数が多い） ExifLib を使用して写真（jpegファイル）へ埋め込まれたジオタグ（GPS情報）を得てみます。
※System.Linq を使用しています。

- [EXIFタグ一覧](http://www.vieas.com/exif23.html) - INAGAKI さんのページ

#サンプルコード
「NuGet パッケージの管理」で、プロジェクトへ ExitLib を取り込みます。

```C#
namespace SampleProject
{
  public class Sample1
  {
    /// <summary>
    /// 指定されたファイルのジオタグを読み込み、GoogleMapでその位置を示します。
    /// </summary>
    /// <param name="jpegFilePath">写真ファイルのパス。</param>
    public void BrowseMap(string jpegFilePath)
    {
      var rd = new ExifLib.ExifReader(jpegFilePath);
      double[] lat, lng;
      string rLat, rLng;
      rd.GetTagValue<double[]>(ExifLib.ExifTags.GPSLatitude, out lat);
      rd.GetTagValue<double[]>(ExifLib.ExifTags.GPSLongitude, out lng);
      rd.GetTagValue<string>(ExifLib.ExifTags.GPSLatitudeRef, out rLat);
      rd.GetTagValue<string>(ExifLib.ExifTags.GPSLongitudeRef, out rLng);
      if((lat != null) && (lng != null))
      {
        var latitude = lat.Reverse().Aggregate<double>((s, v) => { return s / 60 + v; }) * (rLat.Equals("S") ? -1 : 1);
        //var latitude = (lat[0] + lat[1] / 60 + lat[2] / 3600) * (rLat.Equals("S") ? -1 : 1); でもよいでしょう。
        var longitude = lng.Reverse().Aggregate<double>((s, v) => { return s / 60 + v; }) * (rLng.Equals("W") ? -1 : 1);
        var url = "https://www.google.com/maps/?q=" + latitude.ToString() + "," + longitude.ToString();
        System.Diagnostics.Process.Start(url);
    }
  }
}
```

GPSLatitude と GPSLongitude の値は double[] 型で取得でき、度、分、秒の順に入っています。また、GPSLatitudeRefには文字列（string型）で北緯:Nか南緯:Sか、GPSLongitudeRefには東経:Eか西経:Wが入っています。
(例)
<img width="259" alt="p1.png" src="https://qiita-image-store.s3.amazonaws.com/0/100206/705d92a3-4c81-81e2-db9c-c21b255037c6.png">

この「度、分、秒」の緯度・経度の値を10進数の値に変換して、さらに南緯や西経の場合は符号を反転させて、GoogleMap サーバへ渡すURLに埋め込んでいます。
大抵が世界測地系で記録されているようなので、測地系の変換をせずとも GoogleMapでそのまま表示できます。

#備考
photo.exif パッケージも使用してみました。こちらは次のようなコードで、EXIF情報を丸ごと得られるのが利点です。
ただ他の情報はうまく取れるようですが、ジオタグ（GPS情報）は整数部分だけしか取得できませんでした。

```C#
var exifInfo = (new photo.exif.Parser()).Parse(jpegFilePath).ToArray();
```

<img width="409" alt="p2.png" src="https://qiita-image-store.s3.amazonaws.com/0/100206/69ee724c-5e03-a71b-4af1-5573afd7f3fb.png">
Python > datetime > 実装 > 終了日、インターバル、開始日を指定して、インターバルごとに戻り表示する

```txt:動作確認
Python 3 (ideone)
```

以下の実装を行う。

- 終了日から始める
- インターバルごとに日付を戻す
- 開始日を超えた日付を表示して停止する

datetimeのtimedelta()を使うようだ。
https://docs.python.jp/3/library/datetime.html

### code

http://ideone.com/maiFmH

```py3
from datetime import datetime as dt
from datetime import timedelta

ENDSTR = "20170202"
STARTSTR = "20161031"
INTERVAL_DAY = 13

enddt = dt.strptime(ENDSTR, '%Y%m%d')
startdt = dt.strptime(STARTSTR, '%Y%m%d')

wrkdt = enddt
while True:
    print(wrkdt)
    if wrkdt < startdt:
        break
    wrkdt = wrkdt + timedelta(days=-INTERVAL_DAY)

```

```txt:run
2017-02-02 00:00:00
2017-01-20 00:00:00
2017-01-07 00:00:00
2016-12-25 00:00:00
2016-12-12 00:00:00
2016-11-29 00:00:00
2016-11-16 00:00:00
2016-11-03 00:00:00
2016-10-21 00:00:00
```
python3.5環境構築メモ

#なぜかpython3系環境を構築しようと思ったので、作ってみたメモ
環境はMac OSX Sierra

##pyenv を使う
Homebrewは入れてあったので、そのまま

`$brew install pyenv`

`$echo 'export PATH="$HOME/.pyenv/bin:$PATH"' >> .bash_profile`
`$echo 'eval "$(pyenv init -)"' >> .bash_profile`
なんで.bashrcに書いてるんだろう？
気にせず.bash_profileに書く

##python 3.5

`$pyenv install 3.5.0`

zlibがないよエラーで怒られた
zipimport.ZipImportError: can't decompress data; zlib not available

xcode-select --install をオススメされた

`$xcode-select --install`
しばし待つ。

`$pyenv install 3.5.0`
OK

##anaconda
python3.5系で使えるanacondaがよくわからない
どうも4.2あたりはいいらしいので、anaconda3-4.2.0をいれることに

`$pyenv install anaconda3-4.2.0`

ここでちょっとつまる
`$python --version
Python 3.5.0`

`import numpy`
で、そんなライブラリないんですけど？　と。

うーん。。
`$pyenv global anaconda3-4.2.0`

これで、
`$python --version
Python 3.5.2 :: Anaconda 4.2.0 (x86_64)`

で解決
[opencvエラー]need more than 2 values to unpack


領域を切り出したい時のfindContoursがopencvのバージョンによって引数が違う。


#バージョンの確認方法
２系と３系で引数が変わってる。

```
$ python

Python 2.7.6 (default, Oct 26 2016, 20:30:19) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'2.4.13.2'
>>> exit()
```

#エラー内容

```
_, rect_contours, _= cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
ValueError: need more than 2 values to unpack
```

#関数を見る

##2.4

Python: cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]]) → contours, hierarchy
http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#findcontours

##3.1.0
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html


#修正箇所
今回の場合は3系のコードを2系で動かしたかったので

```
_, rect_contours, _= cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
```

↓

```
rect_contours, _= cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
```

に修正した。
【Unity】ForwardレンダリングとDeferredレンダリングの違いを軽くまとめてみた

# はじめに
レンダリングに関する理解を深めるため、ForwardレンダリングとDeferredレンダリングの違いを自分なりに軽くまとめてみました。

# **Forwardレンダリング**
Forwardレンダリングでは、基本的に以下のようにレンダリングが実行されます。
>![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/0149b249-9451-370e-fdc0-cedf0437f0c4.png)

オブジェクトごとにライティング計算が実行されます。


# **Deferredレンダリング**
Deferredレンダリングでは、基本的に以下のようにレンダリングが実行されます。

>![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/c8f516f2-c061-75a9-bbb7-7c0788aa1764.png)


スクリーン上の必要なピクセルのみにライティング計算が実行されます。 


# ForwardとDeferredの比較
**Forward**レンダリングではオブジェクトごとにライティング計算が実行されます。

それに対して**Deferred**レンダリングでは、スクリーン上のピクセルに対してライティング計算が実行されます。 
そのため、DeferredレンダリングではForwardと比較してピクセルシェーダーの負荷が軽くなります。

# 補足
## G-Buffer
**G-Buffer**は、深度情報(Z値)、アルベド値、スペキュラ値、法線情報などのことを指します。
DeferredレンダリングではG-Bufferを使ってZテストやライティング計算が行われます。

Unityでは```BuiltinRenderTextureType.GBuffer0```あたりを参照するとG-Bufferをとってくることができます。

# 参考URL
なぜなにリアルタイムレンダリング
https://www.slideshare.net/SatoshiKodaira/ss-69311865

西川善司の3Dゲームファンのための「KILLZONE 2」グラフィックス講座(前編)
PS3のハイクオリティグラフィックスはDeferred Shadingでキマリ!?
http://game.watch.impress.co.jp/docs/series/3dcg/125909.html

THE RENDERING TECHNOLOGY OF KILLZONE 2
https://www.guerrilla-games.com/read/the-rendering-technology-of-killzone-2

レンダリングパス
https://docs.unity3d.com/jp/540/Manual/RenderingPaths.html

Forward vs Deferred vs Forward+ Rendering with DirectX 11
https://www.3dgep.com/forward-plus/
javascript のコード中に Markdown をヒアドキュメント風に直書きする方法

## 状況

「Web サーバなしで Markdown を描画し、かつヒアドキュメントのように記述する」機会があったので、備忘録としてポストします。

## 準備

以下のファイルを、https://github.com/chjj/marked よりダウンロードしておきます。

- marked.min.js ： Markdown で書かれたテキストを、HTML に変換するライブラリです。

## ポイント

ポイントは md.js に書かれている Markdown テキストを無名関数にコメントとして記述することです。

実行時には、

1. 無名関数は宣言完了と同時(?)に処理される
2. 実行時に関数全体を文字列にする
3. 関数全体を表す文字列から、Markdown 部のみを抽出する

無名関数のまま使えば、HTML ファイルにインラインで記述することもできます。

## サンプルコード

```test.html
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <script src="marked.min.js"></script>
        <script src="md.js"></script>
    </head>
    <body>
<script>
    document.write(marked(doc));
</script>
    </body>
</html>
```

```md.js
var doc =(function(){
/*
# 表題
テスト Markdown ドキュメント

## サマリ

- 良いところ
- 悪いところ

## 良いところ

- 記述が明瞭
- HTML コンバータが豊富で、リッチな描画が可能

## 悪いところ

- コンバータがないとプレビューできない
- 表記法が統一されていない

*/}.toString().match(/[^function\s\(\s\)\s{\s\/\*][\s\S]*[^\s\*\/}]/g).join("\n"));
```
DPAIの試用ツールとしてのStreamRelay.NET.exe

Windowsによるデータ保護API(DPAPI=Data Protection API)の試用ができる

.NET Frameworkでは、DPAPIを気軽に使用することができる。
[System.Security.Cryptography.ProtectedData](https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.protecteddata(v=vs.110).aspx)クラスと[System.Security.Cryptography.ProtectedMemory](https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.protectedmemory(v=vs.110).aspx)クラスである

### DPAIの試用ツールとしてのStreamRelay.NET.exe

こんな感じ

`StreamRelay.NET.exe -LocalPort 0 -LocalInputFile a.txt -RemotePort 0 -RemoteProxy netstream:///?DPAPI^&DPAPIEntropyHex=01020304050607^&DPAPIScope=DataProtection=CurrentUser -Verbose`

### オプション

- DPAPIEntropy[Hex]=<<(Hex)value>> ← 暗号の際のIVみたいなものだと思う
- DPAPIScope="オプション(既定はCurrentUser)"
	- CurrentUser
	- LocalMachine
	- CrossProcess
	- SameLogon
	- SameProcess

#### DataProtection

[System.Security.Cryptography.DataProtectionScope](https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.dataprotectionscope(v=vs.110).aspx)にそれぞれ対応

- CurrentUser
- LocalMachine

#### MemoryProtection

[System.Security.Cryptography.MemoryProtectionScope](https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.memoryprotectionscope(v=vs.110).aspx)
にそれぞれ対応

- CrossProcess
- SameLogon
- SameProcess

---
### 目次へ戻る

[目次というか最初の一歩](http://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)
Googleドライブ「更新後○日経過したファイルを自動削除する」フォルダを作ってみたが、あまり意味なかったメモ

既に当たり前のように試行されていると思いますが、投稿を見つけられなかったので反面教師気取りで置いておきます。

### Google Apps Script を利用して、スクリプトを1時間周期程度で実行するよう設定します。

Google Apps Scriptとは？という方は[簡単な導入方法へ](#Google Apps Script)
「共有フォルダ（3日間保持）」というフォルダ（例）を作り、別途以下のスクリプトを配置します。

*スクリプト動作内容*
>「時限削除したいフォルダの名前」に一致するフォルダ内のファイルの更新日時が4日以上経っていたら、ファイルを「空」で上書きし、ごみ箱に送るといった感じです。指定フォルダがフォルダ内にあっても名前が一致すれば対象となるので、それを利用したフォルダ構成にするのも良いでしょう。

**※指定するフォルダ名は他のものと被らないようにしてください。　名前が一致するフォルダ全てが該当します。**

```js
function trashTemporaryFile() {
  var folderName = "共有フォルダ（3日間保持）"; //時限削除したいフォルダの名前
  var days = 4; //バッファを見て4日
  
  var folders = DriveApp.getFoldersByName(folderName);
  while (folders.hasNext()) {
    var folder = folders.next();
    var files = folder.getFiles();
    while(files.hasNext()) {
      var file = files.next();
      if (new Date() - file.getLastUpdated() > days * 24 * 60 * 60 * 1000) {
        //ファイルを空に（履歴は30日間残る）
        file.setContent("");
        //ゴミ箱に（ファイル完全削除ではない）
        file.setTrashed(true);
      }
    }
  }
}
```

「共有アイテム」で共有されたフォルダの場合、「マイフォルダ」に紐づければ対象となります。

共有権限も操作したかったのですが、他者との共有状態や
各OSのドライブアプリの相性によって制御が様々なので、考えるのをやめました・・
Googleドライブ自体バージョン管理されている上、現状スクリプトではごみ箱にしか配置できないので
ドライブの空き容量が維持できるわけではありません。結局ゴミ箱を空にする必要があります。
だったら、何の意味があるのかといわれると・・「あまり意味なかった」のタイトル回収で結びたいと思います。失礼しました。

>一応、ファイルを空で上書きする前のバージョンは30日保持されるので、30日後には容量確保される想定です。
共有先を閲覧者権限に絞れば「時限ダウンロード」っぽい事を実現したり、ファイルの整理等には利用できます。

もっと良い方法や他に便利なスクリプトがあれば教えてください。（これが本題＾＾；）

# Google Apps Script
自分のGoogleドライブを開いた状態で、以下URLを開いてください。
https://script.google.com/intro

- 所定スクリプトを貼り付けます。

- 「無題のプロジェクト」となっているタイトルを任意のファイル名に変え
- スケジュールは時計のようなアイコンをクリックするとどういった周期で実行するか等の詳細が設定できるので任意に設定します。
- 「保存」ボタンを押します。
（途中でスクリプトのファイル書き込み権限など許可画面が出現しますので指示に従って下さい。）
ドライブに戻るとタイトルをつけた名前でファイルができていると思いますのでこれでセット完了となります。

ファイルを消すと作用しなくなるのでご注意。
【Swift】Accelerateライブラリの行列計算を使った三辺測量の関数

#三辺測量
3つの受信機が取得したRSSIを基に送信機までの距離を推定し、三辺測量を使って送信機の位置を推定する
受信機 A(x1,y1), B(x2,y2), C(x3,y3)
送信機 X(X,Y)
受信機から送信機の距離 A-X: d1, B-X: d2, C-X: d3

![三辺測量の図.png](https://qiita-image-store.s3.amazonaws.com/0/173800/ad49cf70-f3b5-1fd7-2da3-8f46d35c86cd.png)


#ソースコード
```swift:calculatePosition.swift
import Accelerate

func calculatePosition(x1: Double, y1: Double, x2: Double, y2: Double, x3: Double, y3: Double, d1: Double, d2: Double, d3: Double) {
        let A: [Double] = [2*(x1-x3), 2*(y1-y3),
                           2*(x2-x3), 2*(y2-y3)]
        print("matrixA = \(A)")
        let B: [Double] = [(pow(x1, 2)-pow(x3, 2))+(pow(y1, 2)-pow(y3, 2))+(pow(d3, 2)-pow(d1, 2)),
                           (pow(x2, 2)-pow(x3, 2))+(pow(y2, 2)-pow(y3, 2))+(pow(d3, 2)-pow(d2, 2))]
        print("matrixB = \(B)")
        
        let matrixA: la_object_t = la_matrix_from_double_buffer(A, 2, 2, 2, la_hint_t(LA_NO_HINT), la_attribute_t(LA_DEFAULT_ATTRIBUTES))
        
        let matrixB: la_object_t = la_matrix_from_double_buffer(B, 2, 1, 1, la_hint_t(LA_NO_HINT), la_attribute_t(LA_DEFAULT_ATTRIBUTES))
        
        let matrixX: la_object_t = la_solve(matrixA, matrixB)
        
        var bufferA: [Double] = [Double](repeating: 0.0, count: 4)
        la_matrix_to_double_buffer(&bufferA, 2, matrixA)
        var bufferB: [Double] = [Double](repeating: 0.0, count: 2)
        la_matrix_to_double_buffer(&bufferB, 1, matrixB)
        var bufferX: [Double] = [Double](repeating: 0.0, count: 2)
        la_matrix_to_double_buffer(&bufferX, 1, matrixX)
        
        print("matrixX = \(bufferX)")
        
        let X = String(bufferX[0])
        let Y = String(bufferX[1])
        print("Target is (\(X), \(Y))")
    }
```

#注意
iPhoneでGPSを使って緯度経度を取得して使う場合、
緯度経度の値[°(degree)]と送信機と受信機の距離[m]をそのまま使うとおかしな値が出ます。
引数の値は単位を揃えましょう。
WindowsNTサービスとしてのStreamRelay.NET.exe

WindowsNTサービスとして起動させることも可能

### NTサービスとしてインストール

`StreamRelay.NET.exe -install`

設定はレジストリを見るはず。

### NTサービスからアンインストール

`StreamRelay.NET.exe -uninstall`

### NTサービスから起動

内部的に話をすると、
`StreamRelay.NET.exe -service`
と「-service」オプション付で起動した場合、NTサービスから呼び出されたと認識する

---
### 目次へ戻る

[目次というか最初の一歩](http://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)
環境表示プログラムとしてのStreamRelay.jar

`java.exe -Djava.security.policy=StreamRelay.policy -jar StreamRelay.jar`
⇔
`StreamRelay.bat`

### 環境表示プログラムとしてのStreamRelay.jar

`java.exe -Djava.security.policy=StreamRelay.policy -jar StreamRelay.jar -ListSetting`

JavaVM の設定状況などが表示される。

---
### 目次へ戻る

[目次というか最初の一歩](http://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)
Navigation Drawerのスクロールバーを消す方法

##XML上でスクロールバーを消すことはできない
XML上のNavigationViewに対して、以下のようにスクロールバーを消そうとしたが消えない。

```xml
android:scrollbars="none"
```

##NavigationViewの構成
NavigationViewの実態は、FrameLayout。
そして、その中にNavigationMenuViewというRecyclerViewがある。
よって、NavigationViewに対してスクロールバーを消すことはできず、NavigationMenuViewに対してスクロールバーを消すように書く必要がある。

##実装
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
    if (navigationView != null) {
        NavigationMenuView navigationMenuView = (NavigationMenuView) navigationView.getChildAt(0);
        if(navigationMenuView != null) {
            navigationMenuView.setVerticalScrollBarEnabled(false);
        }
    }
}
```
Unicorn + Nginxを理解する

と言っても深すぎるところまではやれないと思うけど、理解しながら利用する方がいいはずなので、できる限りを努める。
# temに置くpidとsocketはなんぞや
## pid (プロセス識別子)
参考：[wikipedia](https://ja.wikipedia.org/wiki/プロセス識別子)
>**pidファイル**
長時間動作し続けるプロセス（例えば MySQL デーモンなど）は、自身のPIDをファイルに書いておき、他のプロセスが参照できるようにしていることがある。

## socket（ソケット）
>ソケット通信では，前もって「待ち合わせた」ところでお互いにソケット同士をつなぎ合わせて通信路を作ります。待ち合わせる場所はソケットの種別によって変わってきますが，最もよく用いられるTCP/IPのソケットでは，ホスト（ホスト名またはIPアドレスで指定）とポート（1から65535までの整数で指定）の組み合わせで待ち合わせます。

参考：[itpro](http://itpro.nikkeibp.co.jp/article/COLUMN/20071031/285990/)
https://ja.wikipedia.org/wiki/UNIXドメインソケット
## …🤔
これだけだとイマイチ正確に理解した気にはなれないが、プロセス間やネットワーク間でやりとりをする時に、受け渡しのようなことをするためのものっていう理解で現時点はなった。（ちゃんと勉強しよ）

# で、結局UnicornとNginxでどうやって設定するの？

```rails_root/config/unicorn.rb
#Unicornのログ出力先を指定
#File.expand_pathはパスを絶対パスに解決するメソッド File.expand_path: https://ruby-doc.org/core-2.2.0/File.html#method-c-expand_path
rails_root = File.expand_path('../../', __FILE__)
#ワーカー数を指定する
worker_processes 2
working_directory rails_root

listen "#{rails_root}/tmp/sockets/unicorn.sock" #？？「Unicornのプロセスをlistenするアドレストポートを指定」らしいが…;socketsを追加。
pid "#{rails_root}/tmp/pids/unicorn.pid" #pid fileの位置を指定する。pidsを追加。

#ログの出力先を指定
stderr_path "#{rails_root}/log/unicorn_error.log"
stdout_path "#{rails_root}/log/unicorn.log"
```
再起動（のうちの停止）を変更したパスに従って変更する。

```/usr/local/etc/nginx/nginx.conf
upstream unicorn {
        # nginxとunicornの連携
        # unicorn.rbで設定したunicorn.sockを指定
        server unix:{RAILS_PROJECT_ROOT}/tmp/sockets/unicorn.sock; #ソケットはこいつだ！socketsを追加
    }

server {
        listen 8081;
        server_name {PROJECTDOMAIN_FOR_LOCAL};

        root {RAILS_PROJECT_ROOT}/public;

        access_log /usr/local/var/log/nginx/{PROJECT_NAME}_access.log;
        error_log /usr/local/var/log/nginx/{PROJECT_NAME}_error.log;

        client_max_body_size 100m;
        error_page 500 502 503 504 /500.html;

        try_files $uri/index.html $uri @unicorn;

        location @unicorn {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_pass http://unicorn;
        }
    } 
```
マイvim設定を修正（vim-airlineで格好いいvimライフ）


## lightlineからvim-airlineへ

powerlineからvim-airline、そしてlightlineへ切り替えたと思うがその経緯については全く覚えてない。
vim設定の見直しを検討していてなるべく設定の記述が少ない方がいいと思いvim-airlineに変更した。

## ○や□、▶︎などが崩れる場合の対策

* iterm2 ▶︎ Profiles ▶︎ Text ▶︎ Unicodeの「Treat ambiguous-width characters as double width(not recommended)をチェックする。
* vimrcに「set ambiwidth=double」を追加

__注意：vimだけを使うことであればこの設定でも問題がないが、tmuxと一緒に使う場合はやめた方がいい。powerline系のステータスバーが崩れてしまう。__

## vimrcのvim-airline設定

* Non-ASCII FontもPowerline用のrictyに変更する。
![스크린샷 2017-06-13 15.38.32.png](https://qiita-image-store.s3.amazonaws.com/0/93752/d0b0d17e-a8bc-35ed-cccb-0c9df58c4167.png "스크린샷 2017-06-13 15.38.32.png")

powerlineのフォントが設置されてない場合は正常に表示されない。
rictyについては[こちら](http://qiita.com/park-jh/items/3c5b9b4aa5619a3631b3)を参考にしていただければと思う。

* Powerline用のrictyに変更してもambiwidth=doubleになっていると◀︎や⮃などが崩れてしまう。
* ◀︎や⮃は旧Powerline用のsymbolsを使う。

結果としては下記のように設定すれば丁度見栄えがいい感じになった。

```vim
" ○や□の文字が崩れる問題を回避
set ambiwidth=double

... snip ...

Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'

... snip ...

" Powerline系フォントを利用する
set laststatus=2
let g:airline_powerline_fonts = 1
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#tabline#buffer_idx_mode = 1
let g:airline#extensions#whitespace#mixed_indent_algo = 1
let g:airline_theme = 'papercolor'

if !exists('g:airline_symbols')
  let g:airline_symbols = {}
endif

" unicode symbols
let g:airline_left_sep = '»'
let g:airline_left_sep = '▶'
let g:airline_right_sep = '«'
let g:airline_right_sep = '◀'
let g:airline_symbols.crypt = '🔒'
let g:airline_symbols.linenr = '␊'
let g:airline_symbols.linenr = '␤'
let g:airline_symbols.linenr = '¶'
let g:airline_symbols.maxlinenr = '☰'
let g:airline_symbols.maxlinenr = ''
let g:airline_symbols.branch = '⎇'
let g:airline_symbols.paste = 'ρ'
let g:airline_symbols.paste = 'Þ'
let g:airline_symbols.paste = '∥'
let g:airline_symbols.spell = 'Ꞩ'
let g:airline_symbols.notexists = '∄'
let g:airline_symbols.whitespace = 'Ξ'

" powerline symbols
let g:airline_left_sep = ''
let g:airline_left_alt_sep = ''
let g:airline_right_sep = ''
let g:airline_right_alt_sep = ''
let g:airline_symbols.branch = ''
let g:airline_symbols.readonly = ''
let g:airline_symbols.linenr = ''

" old vim-powerline symbols
" let g:airline_left_sep = '⮀'
" let g:airline_left_alt_sep = '⮁'
let g:airline_right_sep = '⮂'
let g:airline_right_alt_sep = '⮃'
" let g:airline_symbols.branch = '⭠'
" let g:airline_symbols.readonly = '⭤'
" let g:airline_symbols.linenr = '⭡'
```

上記の設定で表示されるvim画面はこうなる。
![스크린샷 2017-06-13 21.34.10.png](https://qiita-image-store.s3.amazonaws.com/0/93752/4c1bfb12-f50c-86bf-ae17-b9871fc5b30d.png "스크린샷 2017-06-13 21.34.10.png")

## tmuxline.vimを使う場合

tmuxline.vimはtmuxのステータスバーを作るためのgeneratorだ。
詳細については次の記事を参考にしていただければと思う。

* http://qiita.com/park-jh/items/ad8535b11196b58177a4

ここが問題だが、iterm2のambiguous-widthやvimrcのambiwidth=doubleがある場合、tmuxのステータスバーが崩れてしまう。
一部の絵文字を正常に表示させる対価としては失ってしまうのが大きい。
そもそも使うのも推奨されていないし、powerlineを使っている場合は画面崩れの障害ポイントになる可能性が高い。
aws-cliの環境を切り替える

#プロファイルの作成
`aws configure --profile XXX`
XXXのプロファイルを作成できる

AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: 
Default output format [None]: 

※既存のものはdefaultとして登録されている

##確認
`cat .aws/config`
`cat .aws/credentials`

#プロファイルを利用してコマンド実行
`aws s3 ls`
`aws s3 ls --profile XXX`
環境が切り替わっているのが確認できる

# 固定
`export AWS_EB_PROFILE=XXX`
RSpec で安全に Timecop する


タイトルは釣りで、実はTimecopは不要という話をします。てへぺろ

Rails 4.1 以降、 ActiveSupport に travel/travel_to メソッドが実装されたのでこれを使おう。
https://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html
travel には相対時間（1日前、とか）、 travel_to には時刻（2000年1月1日とか） を指定して使う。
いずれも Timecop の freeze 相当で時間の流れは止まる。

使用するには include が必要。 rails_helper.rb に1行追加する

```rb
RSpec.configure do |config|
  #...
  config.include ActiveSupport::Testing::TimeHelpers
  #...
end
```

travel しておいて travel_back し忘れると他のテストに影響してしまうため、以下のように block 内で処理すると安全。

```rb
context "leap day" do
  around do |e|
    travel_to('2016-2-29 10:00'.to_time){ e.run }
  end
  it { is_expected.to be_success }
end
```

to_time は 自動的にやってくれるので、実は以下のようにも書ける。可読性アップ。

```rb
    travel_to('2016-2-29 10:00'){ e.run }
```


ところで、 Timecop だと可能な block のネストが travel/travel_to では出来ない
http://qiita.com/akicho8/items/4b2b12786a385ef94731
という指摘があり、これに対応する issue が出されたりもしたが、最終的に Rails コミュニティが出した結論は「ネストするな」ということで、5.1.0 以降はブロックのネストで例外が発生するようになった。
https://github.com/rails/rails/pull/24890
block の中で block 無しをコールするのは許されており、その場合効果は累積される。ブロックを抜けた段階で travel_back してフルリセットされる。ブロック内で travel_back を呼んでしまうとその行以降は普通の現在時刻に戻ってしまうので注意。

```rb
context "leap day" do
  around do |e|
    travel_to('2016-2-29 10:00'){ e.run }
  end
  it do
    travel -1.day
    expect(Date.current).to eq '2016-2-28'.to_date
    # もしここで travel_back すると
    # この行は2月29日ではない
  end
end
```
時間をずらしたうえで freeze はさせたくない場合や、時間の進み方を変えたい場合は Timecop を使おう。
滅多にないけど。
Rails5をproduction（本番環境）で起動する時に嵌ったこと

## 本番環境でrails serverする
`$ rails server --environment production`
参考：http://somethingpg.hatenablog.com/entry/2013/12/22/101528

## なにもせずにやるとエラーが出ます🤔
`An unhandled lowlevel error occurred. The application logs may have details.`
とブラウザに出ておこられる。

```rails_root/config/secrets.yml
development:
  secret_key_base: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

test:
  secret_key_base: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
```
これを解決するには以下のターミナルコマンドが必要です。

```(A).
$ export SECRET_KEY_BASE=`bundle exec rake secret`
```
試しに`$ bundle exec rake secret`を打ってみると、長いキーが帰ってきます。
毎度打ちたくないので、(A)を.hashrc(だっけ、.bash_profileだっけ）に記入しておくといいだろう。
参考：http://blog.naichilab.com/entry/2015/12/05/232651

## css (assets全般) が読み込まれない🤔
webページのリソースを見るとエラーが出ていて`Failed to load resource: the server responded with a status of 404 (Not Found)`とおこられてる。
ターミナルで
`$ RAILS_ENV=production bundle exec rake assets:precompile`
を実行して、次のファイルの箇所をtrueに直す。

```rails_root/config/environments/production.rb
config.assets.compile = true
```
Rails再起動が多分必要。
参考：http://stackoverflow.com/questions/9888724/failed-to-load-resource-the-server-responded-with-a-status-of-404-not-found

## ローカル開発環境からサーバへ移った時にsecret_key_baseが無いとおこられ続ける🤔
SECRET_KEY_BASEの環境変数が正しく収容されているか、確認してみようってことで

```
$ export -p | grep SECRET_KEY_BASE
declare -x SECRET_KEY_BASE="Could not locate Gemfile or .bundle/ directory"
```
いろいろいじって`rake secret`がソラで実行できるようになればよし。主にインストール先の問題だろう。
その後もrails sを実行しようとするとpermission errorで書き込めないファイルがあるとかで、いろいろ調べて自分のローカルの実行できている環境とls -laで照らし合わせていくと、xの権限がtmpとlogフォルダに足りないのが原因だった模様。
`$ chmod 755 -R tmp`などとして、ようやく解決。
最後の方はやや荒技っぽくなったけど、ひとまずサーバでローカルに立ち上げることには成功した。

## Unicorn + Nginxでまだだめ🤔

sudoでunicornを起動してしまうと、ログファイルがルート権限になってしまい、想定外の不具合につながる。
起動がルート以外でできないのは、ポート80番がルート権限を必要とするため。なので、Nginxの設定ファイルをいじり、listenするポートを8080番など1024以降の番号にし、自宅ルータをWAN80番からLAN8080番に転送するように設定する。
これで、sudoを使わなくともサーバを起動できるようになったはずだ。
Powershell で gdrive(Google Drive CLI Client)を動かす

MacとLinuxはREADMEに書いてあるのに、Windowsのやり方が書いてなかったので
# 手順

1. (https://github.com/prasmussen/gdrive) から自分の環境にあうexeファイルをダウンロードする

2. コマンドを簡単に使えるようにする

    下記いずれか一つを行う

    3. エイリアスを設定する
        
        ```
        PS> Move-Item $env:USERPROFILE\Downloads\gdrive-windows-x64.exe $env:USERPROFILE\Documents\WindowsPowerShell\
        PS> Set-Item -Path env:Path -Value "$env:Path;$env:USERPROFILE\Documents\WindowsPowerShell\"
        PS> Set-Alias gdrive gdrive-windows-x64.exe
        ```

        ただし、 `Set-Item`, `Set-Alias` はPowerShellを再起動すると消える。
        つまり起動するごとに実行しなければならない。
        それはめんどくさいので、
        
        ```
        PS> code $PROFILE
        ```

        等でエディターを開き上記の `Set-alias gd ..... dows-x64.exe` を書き加える。
        $PROFILEが大きくなりすぎた場合は `Export-Alias`, `Import-Alias` を活用するのも良いだろう。

    4. Pathを通す。
    ついでに必要に応じてリネーム。

        ```
        PS> Move-Item $env:USERPROFILE\Downloads\gdrive-windows-x64.exe $env:USERPROFILE\bin\gdrive.exe        
        ```

        ファイルが移動されていることを確認

        ```
        PS C:\WINDOWS> Get-ChildItem $env:USERPROFILE\bin | Where-Object{$_ -like "gdrive*"}
        ```

        [Windowsボタン] を押して「環境変数」とタイプ、サジェストされた「環境変数の編集」をクリック。
        Path に `C:\Users\<USERNAME>\bin` を追加して保存する。
    
    1. 実行時に指定する
    `gdrive` コマンドの global option として

    ```
    global:
  -c, --config <configDir>         Application path, default: C:\Users\<USERNAME>\AppData\Roaming\.gdrive
  --refresh-token <refreshToken>   Oauth refresh token used to get access token (for advanced users)
  --access-token <accessToken>     Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users)
    ```

    といったものがある。
    このうち `-c, --config <configDir>` でアプリケーションのパスを指定しても実行できる。


5. Powershell 上で `gdrive about` か `gdrive list`を実行

6. Authentication を要求されるのでそこに表示されているURLをコピーしブラウザに貼り付けて移動

7. ログインして許可を押すとコードが発行されるのでそれをPowershellに貼り付けEnter

8. Powershell 上でもう一度 `gdrive list` 実行

9. Google ドライブ上のファイルが表示されたら、おめでとう！無事Powershell上で`gdrive`コマンドが使えるようになったよ！やったね


# おまけ
上記のコードでは全てCmdletをフルネームで書いているが、当然エイリアスを使っても良い

```
PS> Get-Alias | Where-Object {$_.Definition -in "Move-Item", "Set-Alias", "Remove-Item", "Get-Alias", "Where-Object"}

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           ? -> Where-Object
Alias           del -> Remove-Item
Alias           erase -> Remove-Item
Alias           gal -> Get-Alias
Alias           mi -> Move-Item
Alias           move -> Move-Item
Alias           mv -> Move-Item
Alias           rd -> Remove-Item
Alias           ri -> Remove-Item
Alias           rm -> Remove-Item
Alias           rmdir -> Remove-Item
Alias           sal -> Set-Alias
Alias           where -> Where-Object
```

というようにAliasが設定されており、検索できる。
例えば今の `Get-Alias | Where-Object {}` は `gal|?{}` と書くこともできる。
ユーザーフォルダも `$env:USERPROFILE` で書いたが `$HOME` でも良いし、他のシェルよろしく `~` でも(初期設定では)同様の挙動だと思う。また、.NETも使えるので `[Environment]::GetFolderPath("MyDocuments")` で `Documents` フォルダを検索しても良い。
CentOS7 で CGI が /var/tmp に書き込みできなくなった件 (systemd の PrivateTmp)

# 何があったか

超絶古い C の CGI をパブリッククラウドへ移行させる作業の中で、その CGI が `mkstemp()` 関数を使ってテンポラリファイルを作成しようとしてエラーになりました。以下は頑張って `strace` して取得したシステムコールです。

```
open("/var/tmp/hoge/temp_k6KF97", O_RDWR|O_CREAT|O_EXCL, 0600) = -1 ENOENT (No such file or directory)
```

以前の環境は CentOS5.5 の Apache2.2 で、新しい環境は CentOS7.1 の Apache2.2 です。
(本当は Apache2.4 を使いたかったのですが諸般の事情で 2.2 をソースインストールすることに)

書き込みディレクトリのオーナーやパーミッションは問題ない (apache ユーザーが書き込みできる) のにエラーが出ます。

# 試行錯誤

試しにディレクトリのパーミッションをフルアクセスにして、`mkstemp()` 関数を使ったテストプログラムを作ってターミナル上で叩いてみたところ、問題なくテンポラリファイルが作成できました。
しかしこれをWebサーバーから叩ける場所に置いて、CGI としてブラウザーから実行させるとやはりファイルが作成されません。ファイルディスクリプタが獲得できないのです。

```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main(void)
{
        char filename[] = "/var/tmp/hoge/temp_XXXXXX";
        int i = 30;
        int fd;
 
        sleep(i);
        fd = mkstemp(filename);
        printf("Content-type: text/plain\n\n");
        printf("result: fd: %d\n", fd);
}
```

# 解決策が見つかる

ログイン権限を持たないユーザーが /var/tmp に書き込みできないのだろうか…とか途方に暮れてあれこれ調べていたところ、「Yahoo!知恵袋」の質疑応答にあたりました。

- [CentOS7で/tmpに書けないCentOS7を使ってWEBアプリを実行したところ... - Yahoo!知恵袋](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13148498553)
- [centos7 の apache から php などで /tmp/ でデーターを落とすと/tm... - Yahoo!知恵袋](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13154629533)

これを読んでいてハッと気づきました。そういえば CentOS7 でソースインストールした Apache2.2 を systemd でコントロールできるようにするために、なんかファイルを置いたんだった!
慌てて `/etc/systemd/system/httpd.service` を覗くと、果たして上記のページに書かれていた設定がありました。

```
[Unit]
Description=Apache Web Server 2.2
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
ExecStart=/usr/local/apache2/bin/apachectl -k start
ExecReload=/usr/local/apache2/bin/apachectl graceful
ExecStop=/usr/local/apache2/bin/apachectl -k stop
PrivateTmp=true  # <- これ
LimitNOFILE=infinity

[Install]
WantedBy=multi-user.target
```

これを、

- `PrivateTmp=false` にする。
- `sudo systemctl daemon-reload`
- `sudo systemctl restart httpd`

してから改めて CGI を動かしたところ、テンポラリファイルが `/var/tmp` 配下に作成されました。

systemd の定義ファイルを見よう見まねで作っていて、各項目の意味をちゃんと理解していなかったのがハマった原因です。ちゃんと勉強します…。

# 要するにどういうことか

CentOS7 から採用された systemd で、登録したサービスが使う `/tmp` や `/var/tmp` を、OS標準のものではなくサービス専用のものを用意して提供してくれる仕組みです。別プロセスからこの配下のファイルを操作されてしまうとセキュリティの問題が発生することがあるため、それを避けるための対策として提供された機能のようです。
(参考: テンポラリファイルの扱いについてまとめた記事: [情報セキュリティ技術動向調査（2008 年下期）：IPA 独立行政法人 情報処理推進機構](https://www.ipa.go.jp/security/fy20/reports/tech1-tg/2_05.html))

インターネット側から不特定多数の人が叩くプログラムでテンポラリ領域を使うのは危険、ということのようです。

# その他参考資料

- [はじめてのsystemdサービス管理ガイド ｜ Developers.IO](http://dev.classmethod.jp/cloud/aws/service-control-use-systemd/)
- [Systemd入門(4) - serviceタイプUnitの設定ファイル - めもめも](http://enakai00.hatenablog.com/entry/20130917/1379374797)
Laravel5.2でエラーメッセージをカスタムしてみた

# やりたいこと

required_ifで 「◯◯が▲▲の場合、□□も入力してください」で、▲▲がフラグ的なものでそのまま出したんでは伝わりづらいのでカスタムしたかった

# コード
tags の１つ目は、tag_requiredが1の場合に必須にしたい。
Validator::makeの第２引数までの指定だと
「tag_requiredが"1"の場合、tags.0を指定してください」
などとイケてないメッセージがでる（フォーマットは多言語設定に準じる）


```Controller.php
$validator = Validator::make( $request->all(), [
  'id'               => 'bail|required',
  'tags'             => 'bail|required|array|max:10',
  'tags.0'           => 'bail|required_if:tag_required,1|max:20',
  'tag_required'     => 'bail|required|boolean'
], [], [
  'id'               => 'ID'
  'tags'             => 'タグ',
  'tags.0'           => 'タグ1番目',
  'tag_required'     => 'タグの必須指定'
] );
$validator->addCustomValues([
  'tag_required' => ['1' => '１つ以上必須にする' ]
]);
if($validator->fails()) {
  // any
}
```

こうすると、
「タグの必須指定が"１つ以上必須にする"の場合、タグ1番目を指定してください」
と、まっとうな日本語で出すことができる。

~~ひっっっさしぶりのphpで色々アレ~~
Unity初心者へ　作業が水の泡にならない為の設定

Unityの開発を進めていると、誰もが最初は躓くであろう惑わし機能…
#実行中（再生中）は作業しても反映されない。

この機能があるお陰で、実行中に機能の微調整をして、消えて二度手間になったりする。
細かい調整を加えたあと、実行中と気付いたらもう最悪である。

##対策
実行中画面の色を変える設定を行う。
【実行前】
<img width="1395" alt="スクリーンショット 2017-06-13 15.04.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/47901/3c00fdcd-a6f7-3f2e-8673-674b8ac3a083.png">


【実行中】
<img width="1142" alt="スクリーンショット 2017-06-13 15.02.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/47901/0519fa87-5221-8afc-5f97-a81f3fa4ee21.png">

###いやーこれならわかりやすい。

【方法】
Unityの[Preference...]を選択後、[Color]>[Genreal]の[Playmode tint]の色を任意の色へ変更するのみ。
<img width="218" alt="スクリーンショット 2017-06-13 15.04.48 1.png" src="https://qiita-image-store.s3.amazonaws.com/0/47901/681443e1-b443-2f20-ddd4-9e8f01d8dec1.png">

<img width="497" alt="スクリーンショット 2017-06-13 15.04.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/47901/fe61afa7-c0d6-32da-ebe2-e4caef2753ee.png">

※あまり原色に近いと目が疲れそうなので、おしゃれな色を選ぼう。
【色：参考】
http://www.colordic.org/w/
Ubuntu 16.04 LTS (64ビット版) にUnityを導入する方法

Ubuntu 16.04 LTS (64ビット版) にUnityを導入する方法についてまとめてみます。
※ここでのUnityはユーザインタフェースの方ではなく、__ゲームエンジン__の方ですのでご注意ください。

#インストール方法
1. [Linux版Unityエディター : 試験的ビルドをリリースしました – Unity Blog](https://blogs.unity3d.com/jp/2015/08/26/unity-comes-to-linux-experimental-build-now-available/)から`オフィシャル 64-bit .deb パッケージ`をダウンロードします。  
![Linux版Unityエディター : 試験的ビルドをリリースしました – Unity Blog_023.png](https://qiita-image-store.s3.amazonaws.com/0/52291/04136e87-594a-1d9d-b44c-d099ba4abf3f.png)
2. `sudo apt install ./unity-editor-5.1.0f3+2015082501_amd64.deb`コマンドを実行し、debパッケージをインストールします。

#アクティベーション方法
起動時にログイン画面が出てくる場合には、以下の手順でアクティベーションを行う必要があります。

3. 端末を開きます。
4. `LD_PRELOAD=/lib/x86_64-linux-gnu/libresolv.so.2 /opt/Unity/Editor/Unity`コマンドを実行し、Unityを起動します。
5. アクティベーションを行います。  
※Unityへのユーザ登録が必要です。

#起動方法
DashホームからUnityを選択して起動します。

#参考文献
* [Service not Available Please try later | Unity Community](https://forum.unity3d.com/threads/service-not-available-please-try-later.403264/)
* [【Linux FAQ】.debファイルをダウンロードしたのですが、どうやってインストールすればいいですか？ | Linux Fan](https://linuxfan.info/post-1881)
Tmux Plugin Manager（tpm）


## tpmとは

* tmuxのpluginを管理するためのツールである。
* vimのvim-plugやnodeのnpm、rubyのbundlerやpythonのpipみたいなもの

## 設置方法

githubのtpmからリポジトリをcloneして設置する。

```sh
% git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
```

~/.tmux.confというdotfileを作って下記の手順通りに使いたいpluginを記述する。

```sh
# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'

# Other examples:
# set -g @plugin 'github_username/plugin_name'
# set -g @plugin 'git@github.com/user/plugin'
# set -g @plugin 'git@bitbucket.com/user/plugin'

# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'
```

大事なのは一番下の部分だ。
tpmの起動は~/.tmux.confの一番下に書く必要がある。
そうではないとせっかく設置したプラグインが使えない。
のちほど説明する。

```sh
% tmux source-file ~/.tmux.conf
```

## 使い方

| キー入力         | 説明                                           |
| ---              | ---                                            |
| prefix + I       | 新しいpluginを設置する                         |
| prefix + U       | pluginをアップデートする                       |
| prefix + alt + u | pluginのリストにないものをアンインストールする |

### 注意点

* prefixのデフォルト値は「ctrl + b」だが、自分好みの設定になっている場合が多い。
* 「prefix + I」と「prefix + U」のIとUは大文字である。
* itermでpluginのアンインストールができない場合がある。altキーの設定を下記のように変更する。
![스크린샷 2017-06-09 18.28.54.png](https://qiita-image-store.s3.amazonaws.com/0/93752/f55f47da-2fa5-4304-7080-6607cc687c5f.png "스크린샷 2017-06-09 18.28.54.png")


## ハマったところ

設置方法にも言及しているが、tpmを起動（run）する部分が一番下に書かれていなければ、設置したpluginを正常に使えない。
最初検索で引っかかった誰かさんの.tmux.confファイルを参考にしたが、これがハマる落とし穴になってしまった。
そのときに参考にしたサイトが[ここ](http://post.simplie.jp/posts/58)だが.tmux.confの一番下にステータスバーの設定を読み込んでいる。
tmuxのステータスバーにバッテリーやCPU使用率などの情報を表示したくて、tpmを利用して関連pluginを設置したが、正常に表示されなかった。
tmux source-file .tmux.confで設定ファイルをリロードするときにちょっとだけ正常に表示され、すぐ消えてしまう。
いろいろ設定ファイルを弄ってみたけど、ダメだったので、pluginではないコマンドで実行して表示する方法に変更した。
（pluginもスクリプト形式で書かれているからコマンドと同様だろうな。）

* そのとき使ったコマンド
  - バッテリー：https://github.com/Goles/Battery
  - 天気：https://github.com/fcambus/ansiweather

これらも結構気に入ったので、諦めていたが、どうにも気になり、もう一度調べた。
そこで見つけたのが設定ファイルの一番下にtpmをrunする部分を記入しないといけないと言う内容だった。

* https://github.com/tmux-plugins/tpm/blob/master/docs/tpm_not_working.md

ネットで探した内容は参考にするだけで、githubや本家のサイトのreadmeとかをちゃんと読んだ方がいい。
英語が苦ってだからといて避けてしまうと痛い目に会う。

## 追記（2017/09/29）

* pluginのコマンドをrunやrun-shellが実行する場合、「...returned 127」というメッセージが表示されたら、pluginが設置されるディレクトリを確認して見よう。何なのかの理由でpluginが設置されない場合がある。tpmも結局はtmuxのpluginをgithubのリポジトリからcloneすることである。僕の場合だと、pluginの名前と同じ名前の空のディレクトリが存在していたが、「prefix + I」で設置できなかった。runやrun-shellの実行の対象がなかったので、「...returned 127」というメッセージが表示された。

## 参考

* https://github.com/tmux-plugins/tpm
ActiveRecordのchanged?が非推奨になっている

# 発生した問題

Rails5.1を使ってみようと思い、いつものようにコードを書いていると、大量のwarningが出てることに気づいた。

```
DEPRECATION WARNING: The behavior of `attribute_changed?` inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after `save` returned (e.g. the opposite of what it returns now). To maintain the current behavior, use `saved_change_to_attribute?` instead. (called from メソッド at /path/to/mode.rb:xx)
```

調べてみると、どうやら書き方が変わるらしい。
https://github.com/rails/rails/blob/master/activerecord%2Flib%2Factive_record%2Fattribute_methods%2Fdirty.rb#L22-L29

save前とsave後で扱うメソッドが変わるようなので、注意が必要。

# 解決方法
## save前

- `{カラム名}_changed?`　の代わりに　`will_save_change_to_{カラム名}?`
- `{カラム名}_was` の代わりに `{カラム名}_in_database`

## save後

- `{カラム名}_changed?`　の代わりに　`saved_change_to_{カラム名}?`
- `{カラム名}_was` の代わりに `{カラム名} _before_last_save`
Mastodonセットアップ時にErrorがでた場合の対処法云々

mastdonをインストールしていますがエラーがでます。
cld3がbundle installでコケた時
https://teratail.com/questions/78220

rails s が失敗して`raise_no_secret_key': Devise.secret_key was not setと言われました。
http://qiita.com/pugiemonn/items/c8fd89a8ea5cb3c7877b

Mastodonインストール時に"rake secret"でエラーが発生する
https://teratail.com/questions/77058

CentOSにrbenvをインストールする方法
http://www.task-notes.com/entry/20150624/1435114800

RAILS_ENV=production bundle exec rails db:migrate でエラー
db:migradeの前に
RAILS_ENV=production bundle exec rails mastodon:maintenance:prepare_for_foreign_keys
Python | マジカルインクリメント

# マジカルインクリメント
```py
# -*- using:utf-8 -*-

import re


def magical_increment(start):
    pattern = re.compile(r'[^0-9A-Za-z]')

    while True:
        yield start

        temp = []
        add = 1
        carry = None

        for c in reversed(list(start)):
            if pattern.match(c):
                temp.append(c)
                continue

            ch = chr(ord(c) + add)
            if c <= '9' < ch:
                ch = '0'
                carry = '1'
            elif c <= 'Z' < ch:
                ch = carry = 'A'
            elif c <= 'z' < ch:
                ch = carry = 'a'
            else:
                add = 0
                carry = None
            temp.append(ch)

        if carry:
            temp.append(carry)

        start = ''.join(reversed(temp))


if __name__ == '__main__':
    gen = magical_increment('Az-8')
    for i in range(5):
        print(next(gen))
```

英数字のみインクリメントします。記号はそのままです。

```bash
Az-8
Az-9
Ba-0
Ba-1
Ba-2
```

# マジカルAdd

```py
# -*- using:utf-8 -*-

import re


def magical_add(start, step):
    pattern = re.compile(r'[^0-9A-Za-z]')

    while True:
        yield start

        temp = []
        add = step
        prev = ''

        for c in reversed(list(start)):
            if pattern.match(c):
                temp.append(c)
                continue

            if c <= '9':
                value = ord(c) + add % 10
                add //= 10
                prev = '0'
                if ord('9') < value:
                    value -= 10
                    add += 1
            elif c <= 'Z':
                value = ord(c) + add % 26
                add //= 26
                prev = 'A'
                if ord('Z') < value:
                    value -= 26
                    add += 1
            else:
                value = ord(c) + add % 26
                add //= 26
                prev = 'a'
                if ord('z') < value:
                    value -= 26
                    add += 1

            temp.append(chr(value))

        if add:
            if prev == '0':
                temp.extend(reversed(list(str(add))))
            elif prev == 'A' or prev == 'a':
                while add:
                    value = ord(prev) + add % 26 - 1
                    add //= 26
                    temp.append(chr(value))

        start = ''.join(reversed(temp))


if __name__ == '__main__':
    gen = magical_add('aZ-1', 5)
    for i in range(5):
        print(next(gen))
```

英数字のみ加算します（この例では５加算しています）。記号はそのままです。

```bash
aZ-1
aZ-6
bA-1
bA-6
bB-1
```
Excelでのドキュメント作成作業を効率化していく（VBA）

# どうでもいい話

最近ドキュメント作成をすることが増えたので、日中はExcelを使います。
少しでも面倒な作業を減らしたいのでマクロ作成するようになってきたので
使ったものは残しておこうと思います。

# 作ったもの（※ 随時更新）

## ▼ 直前に居たページに戻る機能を作る
※ ひとつ前にしか戻れないです。

下記から拝借 + ボタンクリックで移動としたかったのでカスタムしました。
[Excelで直前に参照していたシートに戻る(シートの参照履歴を保持する)](http://d.hatena.ne.jp/sumihira1989/20140629/1404020657)

```vbnet:ThisWorkbook
'PERSONAL.XLSB ThisWorkBook

'WithEventsにてApplicationオブジェクト(Excel全体を示すオブジェクト)に発生するイベントを拾える様にする

'PERSONAL.XLSBに記述することで、全てのExcelファイルに適用される。

Public WithEvents xlAPP As Application



'Excelブックが開いた時に自動実行する。

Private Sub Workbook_Open()

    'アプリケーションオブジェクトを取得

    Set xlAPP = Application



    '標準モジュールの初回呼出し

    '直接呼び出すとエラーになるため、実行時間をずらして呼び出す。

    Application.OnTime Now + TimeSerial(0, 0, 1), "appFirst"

    

End Sub



'シートがアクティブになった時に自動実行する。

'(ブック内)シート間での参照履歴を保持する。

Private Sub xlAPP_SheetActivate(ByVal Sh As Object)

    oldBook = nowBook

    oldSheet = nowSheet

    nowBook = ActiveWorkbook.Name

    nowSheet = Sh.Name

        

End Sub



'Excelウインドウがアクティブになった時に自動実行する。

'以下によりExcelファイルを跨いでも、参照履歴が保持される。

Private Sub xlAPP_WindowActivate(ByVal Wb As Workbook, ByVal Wn As Window)

    oldBook = nowBook

    oldSheet = nowSheet

    nowBook = Wb.Name

    nowSheet = Wb.ActiveSheet.Name



End Sub
```

```vbnet:モジュール
'PERSONAL.XLSB 標準モジュール goBackSheet
'前に参照していたファイル.シートへ戻る(アクティブにする)
'マクロの実行メニューにPublicプロシージャが表示されないようにする。

Option Private Module

'参照履歴
Public oldBook  As String  '前に参照していたブック
Public oldSheet As String  '前に参照していたブック
Public nowBook  As String  '現在参照しているブック
Public nowSheet As String  '現在参照しているブック



'前に参照していたシートに戻る(Activeにする)マクロ

' ここはボタンを作ったときに生成されたファンクションです
Sub 戻る()

    'エラー発生した場合は無視する
    On Error Resume Next
    Workbooks(oldBook).Worksheets(oldSheet).Activate

End Sub


'Excel起動時に自動呼出しされるモジュール

Public Sub appFirst()

    'ファイル読込みに時間がかかるとエラーになるためスキップする
    On Error GoTo nextProc

    'ブック名・シート名を取得
    nowBook = ActiveWorkbook.Name
    nowSheet = ActiveSheet.Name

nextProc:
    

End Sub

```

## ▼ 選択されたセルの値を名前としたシートを作成する（範囲指定も対応）

```vbnet
Sub セルからタブ生成()
'
' セルからタブ生成 Macro
'
' Keyboard Shortcut: Ctrl+t
'
  Dim 項目 As Range
  For Each 項目 In Selection
        ' 「tmp」という名前のシートを複製する
        Worksheets("tmp").Copy Before:=Worksheets("tmp")
        ' 「項目」の値をシートのD8に書き込む
        Range("D8").Value = 項目.Value
        ' 「項目」の値をシートの名前にする
        ActiveSheet.Name = 項目.Value
   Next 項目
End Sub
```

# 参考

- [リストの項目に対応したシートを複数つくりたい](https://kokodane.com/2013_macro_58.htm)
- [Excel VBAでシートをコピーする：Copy](http://uxmilk.jp/47978)
- [VBA セルに値を設定する](http://www.tipsfound.com/vba/07002)
PostFixの送信済みメールの中身を確認する時にやったこと

既存システムで配信しているメールの内容を確認したかった。
とりあえず開発サーバーには入れる状況でメールを確認するまでにやったことをメモ :writing_hand_tone2:

あとで勉強しなおす・・・予定 :hugging:
#PostFixの送信済みメールの中身を確認する時にやったこと

痕跡をさがす

```console
$ tail -f /var/log/maillog
```

痕跡はあった。
ファイルがどこに出力されているか探す

```console
$ postconf | grep home_mailbox
home_mailbox = Maildir/
```

/home/ユーザー名/Maildir/
に出てるらしい。


```console
$ ls /home/tcimail/Maildir/new/
0000000.XXXXXXXXXXXXXXXXX.xxxx
```
new の中にそれらしきファイルを発見！

見てみる。

```console
$ cat /home/tcimail/Maildir/new/0000000.XXXXXXXXXXXXXXXXX.xxxx
```
文字化けしまくり。。 :skull:

ただし文字化けしていない情報を発見！

```console:0000000.XXXXXXXXXXXXXXXXX.xxxx（メールの痕跡と思われるファイル）
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
```

Content-Transfer-Encoding: quoted-printable
なので、nkf -mQでデコードして、nkf -wでUTF-8で出力する

```
$ cat 0000000.XXXXXXXXXXXXXXXXX.xxxx | nkf -mQ | nkf -w
```

見れたよー :thumbsup_tone2:

（参考）
・[MIMEエンコードされたメールのデコード方法](http://qiita.com/sheepland/items/2065ffcc7ec8c03145cc)
・[nkf - コマンド (プログラム) の説明 - Linux コマンド集 一覧表](http://kazmax.zpp.jp/cmd/n/nkf.1.html)
[Linux][chmod] パーミッションを数値で指定する

chmodの755などの指定をちょくちょく忘れるので、基本的なことのメモ

# 指定順

権限の数値の指定順は以下の順になる

オーナー, グループ, その他

| 種別 | 概要 |
|:-:|:-:|
| オーナ－  | ファイル/ディレクトリの所有者のアクセス権  |
| グループ  | ファイル/ディレクトリの所有グループに所属しているユーザーのアクセス権  |
| その他  | オーナーでも所有グループでもないユーザーのアクセス権  |

# 数値

| アスセス権 | 2進数 | 8進数 |
|:-:|:-:|:-:|
|rwx|111|7|
|rw-|110|6|
|r-x|101|5|
|r--|100|4|
|-wx|011|3|
|-w-|010|2|
|--x|001|1|
|---|000|0|

# 指定例

| 権限 | 数値 | 概要 |
|:-- |:-:|:--|
| rw-r--r-- | 644 | オーナー以外は読み取り専用 |
| rw-rw-rw- | 666 | テキストファイルなど |
| rwxr-xr-x | 755 | 実行スクリプトなど |

コマンド例

```bash:パーミッションの変更
$ chmod 755 ファイル名
```

# 参考
[rwxr-xr-xって何？パーティション？Linuxの基本コマンド「ls」の見方](http://blog.maplesystems.co.jp/programming/7001.html)
[パーミッション早見表](http://hayakawa.ddo.jp/beginner/ux/permit.html)
[パーミッションを変更するには](http://www.tohoho-web.com/wwwxx012.htm)
検証ツールで、テキストを直接編集する



検証ツールの
「Console」で


```document.designMode =“on”
```を入力。

[Enter]押すと
Webサイトのテキスト箇所が直接修正できるようになる。
他のテキストも仮で入力できて便利。

<img width="206" alt="スクリーンショット 2017-06-13 13.15.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/145590/1a0b858f-3b42-a088-10f0-2e4921d999f1.png">
Python3インストールからDjangoアプリ作成までの手順



## Macプリインストールの確認
```
$ python --version
Python 2.7.10
$ which python
/usr/bin/python
```

## HomebrewでPython3をインストール

Homebrewでインストールすると、python3.xを`python3`コマンドにシンボリックリンクしたり、後述の`pip`コマンドのシンボリックリンクをしてくれるようなので、便利。

- XCodeはインストール済み
- homebrewはインストール済み


### インストールバージョン確認
```
$ brew search python
app-engine-python             boost-python@1.59             micropython                   python-markdown               wxpython
boost-python                  gst-python                    python                        python3                       zpython
caskroom/cask/kk7ds-python-runtime                                          caskroom/cask/mysql-connector-python
```

### インストール
```
brew install python3
```

### PATH設定
```~/.bash_profile
export PATH=/usr/local/bin:$PATH
```

```
$ source ~/.bash_profile
$ python -V
Python 2.7.10
$ python3 -V
Python 3.6.1
```

## pipのインストール

Pythonのパッケージマネージャ。python3インストール時に一緒についてくるとのこと。

```
$ pip3 list
DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning.
pip (9.0.1)
setuptools (32.2.0)
wheel (0.29.0)
```


`pip.conf`を置いて、フォーマット指定してね、warningされたので対応。
Macは`$HOME/Library/Application Support/pip/pip.conf`にあるらしいが、なかったので作成。

```
$ cd /Users/kumanoshuta/Library/"Application Support"
$ mkdir pip
$ cd pip
$ vi pip.conf

[list]
format=columns
```

```
$ pip3 list
Package    Version
---------- -------
pip        9.0.1  
setuptools 32.2.0 
wheel      0.29.0 
```

## pyenvのインストール

python本体のバージョンや利用パッケージを切り替えるための仮想環境を提供してくれる。

バージョン切替が必要なのか、dockerやvergrantでいいのでは、など疑問なので割愛。


## Djangoのインストール

```
$ pip3 install django
Collecting django
  Downloading Django-1.11.2-py2.py3-none-any.whl (6.9MB)
    100% |████████████████████████████████| 7.0MB 207kB/s 
Collecting pytz (from django)
  Downloading pytz-2017.2-py2.py3-none-any.whl (484kB)
    100% |████████████████████████████████| 491kB 1.7MB/s 
Installing collected packages: pytz, django
Successfully installed django-1.11.2 pytz-2017.2
```

```
$ pip3 list
Package    Version
---------- -------
Django     1.11.2 
pip        9.0.1  
pytz       2017.2 
setuptools 32.2.0 
wheel      0.29.0 
```

### Djangoアプリを生成、起動

```
$ django-admin startproject mysite
$ python3 manage.py runserver 0.0.0.0:8000
Performing system checks...

System check identified no issues (0 silenced).

You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

June 13, 2017 - 04:16:41
Django version 1.11.2, using settings 'mysite.settings'
Starting development server at http://0.0.0.0:8000/

```

なんかエラーがでてるが、起動はできた。





![download.png](https://qiita-image-store.s3.amazonaws.com/0/8585/ec7d3413-5866-6526-25df-fcdc38be1a86.png "download.png")


次は[DB設定](http://qiita.com/shoota_github/items/e6e4e7934aa844917f2d)をする
OSXがDisk Fullで起動できなくなった時

Sierra 10.12.5にUpdateするときにDisk Fullになった。
起動しようとしてもDisk Fullなので起動できない、そんなときに以下で解決しました。


1. Single User Modeで起動
------

電源ボタンを押し、起動する際、 `Command` + `S` を押しながら起動。
Single User ModeではDiskをRead-onlyでマウントする。

一応起動するが、これだとファイルが削除できない。そのため次の方法でRead-Writeでマウントする。

2. Read-Writeでのマウント
------
Single User Mode起動した時、Read-Writeでマウントするには以下のどちらかを使ってねと表示されている。

```
/sbin/fsck -fy
/sbin/mount -uw /
```

しかし、fsckコマンドではファイルシステムが正常かどうかのチェックが走るため、結局Disk Fullとエラーが表示されマウントできない。そのため今回は `/sbin/mount -uw /` を使う。

あとは容量を稼ぐためにファイルを削除していけばなんとかやっていける。