OmniAICreator/Qiita-1.07M huggingface dataset:
ListViewのカスタムViewを作る時、Adapterの更新は、更新用メソッドを作った方がいいと思う

ListViewを継承したカスタムビューを作る事って結構多いと思うんだけど、私はこうしているというメモ。
なぜかListViewを更新するたびにAdapterを再生成してるサンプルとかあって混乱したので。

特徴としては、アダプタに更新用のメソッドを作って、カスタムビューにも更新用メソッドを用意しておく。
他のViewの操作と連動してListViewを更新する場合、アダプタの更新内容を与えるだけで更新できる。

思い切ってAdapterやListの生成時には中身を作らなくてもいいような気がする。その方が更新処理を一箇所にまとめられてわかりやすくなる気がする。

あ、SwipeRefreshLayout を継承してるけど、他のListView系のクラスでも同様だと思う。

ListViewのソース。

```lang:java
public class HogHogeListView extends SwipeRefreshLayout {
    /**
     * @param context
     * @param attrs
     */
    public HogHogeListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        // リストを作る
        listView = new ListView(context);
        listView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        //アダプタを作ってListViewに入れる
        HogeAdapter adapter = new HogeAdapter(activity,hogeList);
        listView.setAdapter(adapter);
        // リストを追加
        addView(listView);//ListViewのインスタンスを格納する事で、レイアウトの「@android:id/list」に自動的に割り当てられます
        setOnRefreshListener(onRefreshListener);//ひっぱった時のリスナ登録
    }

    /**
     * リストビューの更新処理。
     */
    public void reflesh(){
        HogeAdapteradapter = (HogeAdapter)listView.getAdapter();
        adapter.refleshItemList(hogeItemList);
        adapter.getFilter().filter(s);//フィルタ実行。ソートもここで実行する。再描画も担当する

    }
}
```
次。アダプタのソース。更新用のメソッドを作っておくこと。

```lang:java
public class HogeAdapter extends ArrayAdapter<HogeItem>
	public HogeAdapter (Context context, List<HogeItem> list)
	{
		super(context,R.layout.hoge_list_item);
		this.context = context;
		this.sourceList = new ArrayList<HogeItem>(list);
	}
    ～ 描画処理とか基本的なのは省略 ～
    /**
     * ファイルのリストをリフレッシュする
     * @param itemList
     */
    public void refleshItemList(List<HogeItem> itemList){
        sourceList.clear();
        sourceList = new ArrayList<HogeItem>(itemList);
    }
}
```
ゲーム開発におけるクラスの基礎設計

ゲーム開発においてバグの８割は初期化ミスであると考えている。
ここでは、初期化を可能な限りミスしないためのクラスの基礎設計について説明する。

##必要なメソッド
クラスを作る際に以下のメソッドを必ず定義する。

* コンストラクタ（C++11からはなくてもよい）
* デストラクタ
* Initialize
* Finalize

クラスを作る際に以下のメンバを定義する。

* InitializeParam構造体を保持する変数
* bool型の初期化済み判定変数


それぞれの役割について説明をする。

###コンストラクタ
メンバ変数を初期化する。
C++11からは変数定義時に初期化できるため、デフォルトコンストラクタしか必要ない場合は
意図的に定義する必要はない。

###デストラクタ
Finalizeメソッドを呼び出す

###Initialize
実質的な初期化はこのメソッド内で行う。
初期化に必要なパラメータも基本的にInitializeメソッドに渡す。
引数が３つ以上になる場合は、InitializeParamのような初期化構造体を作って渡したほうがよい
メソッドの頭でFinalizeメソッドを呼び出す

###Finalize
肝となるメソッド。
変数を定義したら、即座にFinalizeに終了処理を記述する。
このメソッドが呼ばれたら、如何なる状態からでも正常に終了出来るようにする。
また、２度以上呼ばれた場合でも正常に動作するようにする。


##作成例

```cpp:Hoge.h

/*!
 *@brief 例題クラス
 */
class Hoge
{
public :
	/*!
	 * @brief 初期化構造体
	 */
	struct InitializeParam {
		size_t size;
		size_t value;
	};
	
	/*!
	 * @brief コンストラクタ
	 */
	Hoge() = default;
	/*!
	 * @brief デストラクタ
	 */
	~Hoge() {
		Finalize();
	}

	/*!
	 * @brief 初期化を行います。
	 *
	 * @param param 初期化構造体を設定します。
	 *
	 * @return 正常に終了した場合は true を返します。
	 */	
	bool Initialize(const InitializeParam& param) {
		// 必ずFinalizeを呼んで終了させる
		Finalize();
	
		init_param_ = param;
		
		// バッファを初期化する
		buffer_ = new char[init_param_.size];
	
		// 初期化済みとする
		initialized = true;
		return true;
	}

	/*!
	 * @brief 終了化を行います。
	 */	
	 void Finalize() {
	 	delete[] buffer_;
	 	buffer_ = nullptr;
	 	
	 	// 未初期化状態とする
	 	initialized = false;
	 }
	 
	 /*!
	  * @brief 適当なメソッド
	  */
	  void Func() {
	  	// 初期化されていない場合は何もしない
	  	if (!initialized) return ;
	  	
	  	// 必要な処理を記載
	  	・・・
	  }
	 
private :
	// 変数を定義、必要な変数を初期化する	
	InitializeParam init_param_;	//!< 初期化構造体
	bool initialized = false;			//!< 初期化済み判定変数
	char* buffer_ = nullptr;			//!< バッファ、nullptrで初期化しないと最初のFinalizeでエラーとなる
};

```

##意図
Initializeメソッドはいかなる場合に呼んでも、**必ず初期化される**ことが重要である。
ゲーム開発中はデバッグも含めて意図的にクラスを初期化状態にする必要があることが多々存在する。
余計な事を考えず、Initializeを呼べば必ず初期化状態になることは、それだけで初期化のミスを減らすことになる。

Finalizeメソッドはいかなる場合に呼んでも、**必ず正常に終了される**ことが重要である。
プログラムは上位の管理クラスにより、想定していないタイミングで解放されることは多々存在する。
デストラクタでFinalizeを呼んでおけば、いかなる場合でも正常に終了することが期待できる。
また、正常に終了することが保証されているが故、Initializeの頭でFinalizeを呼ぶことで
いかなる場合でも正常に終了し、正常に初期化することができるのである。


##(追記)コンストラクタ、デストラクタとは別にInitializeとFinalizeを追加する理由
初期化の重要性と手法を記述したが、コンストラクタとデストラクタで初期化、終了化をしない理由を
書かなかったため、知り合いから突っ込みかが入りました。
処理をあえて分ける必要があるパターンをいくつか記載します。

###事前に確保し、使いまわす場合
例えば、シューティングの弾やエフェクトなどのオブジェクトは出入りが激しいため
毎回newを行うと処理が重くなってしまいます。
事前に配列で複数個確保し、使用する際にInitializeをしたほうが処理が軽くなります。
これはplacement newを使う方法でも回避は可能ですが、デストラクタを明示的に呼ぶ必要があるため
Initialize関数を呼ぶほうが綺麗に書けます。

###例外を排除
コンストラクタで問題が発生した場合は例外が投げられ、呼び出し元でtry catchする必要があります。
C++として、この動作は正しいのですがゲームは速度を求められるので、例外設定を切ることが多々あります。
Initialize関数の戻り値で処理の結果を取得することで例外の発生を抑えることが出来ます。

###クラス間で相互に互いのポインタを保持する場合
相互に保持するとなるとコンストラクタでは渡せない、しかし必須パラメータであるため
Set関数で渡すのは微妙であるという時にInitialize関数で必要なパラメータを渡すということが出来ます。
本内容とは外れますが、上記の相互クラスが存在する場合は片方に管理をさせるべきです。
例えば、AクラスとBクラスが存在してAクラスが管理する場合
Aクラスは、BクラスのSet,Getを呼び出すのに対して、BクラスはAクラスのGetのみしか呼び出さない。
このように、Setは一方のみが呼び出すようにしないと処理が複雑になった際に
何が影響して動作しているかが非常にわかりづらくなってしまいます。
ターゲット別に処理を分けたい


特に大したやり方ではないのですが、忘備録として書いておきます。

共通のプロジェクトで、

* ブランドが違う
* 名前が違う
* アイコンが違う

とか、いろいろだし分けたい場合があると思います。ま、普通はないかもしれないけど、いや、あるんです。

で、その場合どうしてるかというと、

	#define brand_1
	#undef brand_2
	
とヘッダーで宣言しておいて、

	#import "define.h"

	#ifdef brand _1
		// ほげほげ
	#else
		// ほげほげ
	#endif

とソース内に書きます。
で、ビルドごとに、defineとundefを書き換えて、、、

って、

んーなことやってたら面倒だし、間違えるので、Preprocessor Macrosの出番です。

大きな区分けの場合によくやるのは、

* Xcodeでターゲットを複製します。
* Build SettingsのなかのPreprocessor MacrosのDebug/

Releaseそれぞれに

	brand_1

とか

	brand_2

っていうのを書いちゃってます。
ヘッダーを書き換えてのビルドせずに、ターゲットを選択するだけで良いのでとっても便利です。

もっと変えたい場合はSchemeを設定してあげると良いですね。
Chrome拡張 | soku_qiita - 即聞いた | Qiita のユーザー・タグ指定検索をマウスを使わずに素早く実行する #chrome_extension

## :musical_score: 概要
Qiita のユーザー・タグ指定検索をマウスを使わずに素早く操作する Chrome 拡張

soku_qiita  
![icon-128.png](https://qiita-image-store.s3.amazonaws.com/0/43480/d2991cf3-b22f-eed6-8054-483761fc0a97.png)

を作成しました。
**即聞いた** です。

## :scroll: 機能
### 基本機能
* メニューにある soku_qiita ボタンを押すか、割り当てたショートカットを入力
* 入力ダイアログが表示される
* カンマ区切りで user, tag を入力
    * `tbpgr,ruby` なら "user:tbpgr tag:ruby"
    * `tbpgr` なら "user:tbpgr"
    * `,ruby` なら "tag:ruby"
* OK をクリック
* キーワード入力欄に検索ワードが設定される
* 検索ボタンをクリック
    * 追加のワードを設定することを考慮し、あえて検索ボタンクリックまで自動化していない

### 例外機能
* 検索ボックスがないページで実行するとコンソールに `no query form` と出力し、処理を終了する

### 補足
はじめは、検索欄の ▼ で表示されるダイアログを利用しようかと思ったのですが、
裏でいろんな属性を制御しているようで、副作用が大きそうだったのでシンプルに
標準の入力ダイアログを利用することにしました。

## <i class="fa fa-history" style="font-size:1em;"></i> 経緯
Qiita の検索メニューはどんどんリッチになるものの、
CUI のショートカットサポートがないのでマウス操作が必要です。
例えば、今の検索機能だと

* マウスで検索欄に移動し、フォーカスをあてる
* ▼が表示される
* ▼をクリックする
* マウスでユーザー指定欄 or タグ指定欄にフォーカスを当てる
* 検索ワードを入力する
* Enter キー

というアクションが必要です。

soku_qiita の機能を利用すれば

* 任意のキー(ショートカット割り当て)
* 検索ワードを入力
* Enter(検索欄に反映)
* Enter(検索の実行)

で実行可能になります。快適。

大分前に運営に要望を出していたのですが、ショートカット厨としては
Chrome 拡張の作り方を覚えた今、拡張を作らない道はありません。

## <i class="fa fa-flag-checkered" style="font-size:1em;"></i> ユースケース
特定のユーザー名、タグ目の検索を 1 入力でも少なく、キーボードから手を離さずに実現したい。

## <i class="fa fa-github" style="font-size:1em;"></i> soku_qiita GitHub
<i class="fa fa-external-link" style="font-size:1em;"></i> [chrome-soku_qiita GitHub](https://github.com/tbpgr/chrome-soku_qiita)

## <i class="fa fa-google" style="font-size:1em;"></i> soku_qiita Chrome ウェブストア
<i class="fa fa-external-link" style="font-size:1em;"></i> [chrome-soku_qiita Chrome ウェブストア](https://chrome.google.com/webstore/detail/sokuqiita/pdbkaalghgacoghbclifkbklgeoaneil)

![soku_qiita_shop.png](https://qiita-image-store.s3.amazonaws.com/0/43480/6061f88f-daf7-b431-fc66-182e5d34b034.png)

## <i class="fa fa-flask" style="font-size:1em;"></i> 試用
### :dog: メニューバーを確認
![usage1.png](https://qiita-image-store.s3.amazonaws.com/0/43480/ea869143-2f46-d729-399c-06fb481d2261.png)

### :cat: Qiita にて chrome-soku_qiita を呼び出し
![usage2.png](https://qiita-image-store.s3.amazonaws.com/0/43480/f42c533e-ca0c-68c5-f0a7-feb69e142c7c.png)

### :rabbit: ダイアログボックスに検索値を入力
![usage3.png](https://qiita-image-store.s3.amazonaws.com/0/43480/19bb5c00-3953-bb71-96da-ef9c104211fe.png)

### :frog: 入力欄に反映
![usage4.png](https://qiita-image-store.s3.amazonaws.com/0/43480/538406ed-88fd-6a04-bd3d-2be036119590.png)

### :koala: 検索の実行
![usage5.png](https://qiita-image-store.s3.amazonaws.com/0/43480/2fcca1c3-dc64-f8ac-2669-d2ef99fbce13.png)

## <i class="fa fa-image" style="font-size:1em;"></i> デモ

アニメーション
![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/43480/a50430ab-c26a-1ed6-ec16-d831a9251444.gif)

## :books: 外部資料
* <i class="fa fa-external-link" style="font-size:1em;"></i> [Chrome Extensions 公式](https://developer.chrome.com/extensions/index)
* <i class="fa fa-external-link" style="font-size:1em;"></i> [chrome-soku_qiita](https://chrome.google.com/webstore/detail/sokuqiita/pdbkaalghgacoghbclifkbklgeoaneil)
Blenderの中のPythonで環境変数を参照するには

# 背景

Python3はprintにカッコが必要なことをninix-ayaのビルドを
昨年やって依頼学習した程度で、Python2のこともChromeのビルドシステムや、
node.jsのエコシステム周りで割と使われてる位しか分かってない。


# Pythonで環境変数を参照

```py3
import os

# どんな環境変数があるか
print(os.environ)

# 特定の環境変数の値を参照
print(os.environ['PATH'])
```

# 関連投稿

- [BlenderをPythonから使えるようになるための第一歩 - Qiita](https://qiita.com/kjunichi/items/96b0effb9ef8e99b09bf)
- [Blenderの中のPythonでカレントディレクトリを知るには - Qiita](https://qiita.com/kjunichi/items/39462dd724acb3eb2b71)
- [直前に生成したプリミティブ等の名称を取得するには - Qiita](https://qiita.com/kjunichi/items/f4e836630613631d3a67)
- [PythonやBlenderでmrubyを動かす - Qiita](https://qiita.com/kjunichi/items/51127edd684cc646e5ec)
- [OSXのBlenderでOpenCVを使う - Qiita](https://qiita.com/kjunichi/items/814993f194d7c07b78bb)

# 関連記事

# 関連記事

- [Blenderで初めてのアドオンを作るまで ～その2～](https://abrakatabura.hatenablog.com/entry/2017/04/28/062856)
- [Blenderで初めてのアドオンを作るまで ～その１～](https://abrakatabura.hatenablog.com/entry/2017/04/11/061849)
- [BlenderでPython使って最速降下曲線を描いてみる](https://abrakatabura.hatenablog.com/entry/2016/05/26/070858)
- [BlenderでエクスポートしたJSONがThree.jsで変な色になる問題が解決](https://abrakatabura.hatenablog.com/entry/2015/12/21/071507)
- [OSXのBlenderでctypesを試した](http://abrakatabura.hatenablog.com/entry/2015/01/31/091848)
- [blenderでgRPC(クライアント＆サーバ)を動かした](https://abrakatabura.hatenablog.com/entry/2019/03/18/212258)
CircleCI で Playframework のプロジェクトを回そうとしたら OOM Killer に殺される件


## process が肥大化して落ちる

CircleCI で Scala のプロジェクトを `sbt test` しようとしたところ、コンテナで4GB以上使ったので異常終了したよ、とのエラーメッセージが出た。ssh login を有効にして様子を眺めていたところ、ひとつ目の java process が 1.7GB 程度まで大きくなった後、2つめの java process が出来上がり同じくらいまで大きくなっていった様子が確認できた。他に起動しているプロセスと合わせると4GBを超えていそうだ。

Playframework だとテストを fork した java process で実行することをすっかり忘れていた。

解決するにはそれぞれの java process が使うメモリ量を指示すれば良い。入っている `sbt` は `.sbtopts` を見てくれるやつなので、 `circle.yml` に次のように書いてやれば良い。

````
dependencies:
  pre:
    - echo '-mem 800' >> .sbtopts
````

これでヒープに 800MB, PermGen に数百MB（忘れた）割り当てられるので 2 process 起動しても溢れない。少なくとも自分の環境では溢れなかった。あふれるようだったらもう少し調整すれば良い。

## その他のはまりポイント

### update-java-alternatives

自分のプロジェクトでは Java 7 syntax のコードが含まれており、そのままだと document 生成まわりで落ちた。`sudo update-java-alternatives -s java-1.7.0-openjdk-amd64` すると落ちなくなった。

### play コマンドを実行しようとして落ちる

そのままだと使っているバージョンと異なるバージョンの play コマンドで実行しようとして落ちた。
sbt を使うようにすれば良い。

````
dependencies:
  override:
    - sbt update
test:
  override:
    - sbt test
````

### `~/.sbt` をキャッシュする

`~/.ivy2` はデフォルトでキャッシュされるので良いが、 `~/.sbt` はされない。
`circle.yml` に次のように書く。

````
dependencies:
  cache_directories:
    - "~/.sbt"
````

### git submodule

デフォルトでは submodule 取ってこないので `circle.yml` に次のようにかけば良い。

````
checkout:
  post:
    - git submodule sync
    - git submodule update --init
````

## CircleCI の感想

* Private repository も無料で動かせるなんてスゴイ！ いままで Drone.io の open source 版を動かしてたけど移行しようかな。
* CI のフェーズが整理されておりすんなり理解できた。
* うまくいかない時は SSH ログインしてチェックすることができるので、すばやく問題を解決することができた。Travis にはない強みだ。
SSL証明書の有効期限の確認をWindowsで行う

定期的にWEBサイトのSSL証明書の有効期限を確認してメールなどでレポートしたい。
なのでコマンドラインやスクリプト等でチェックできないか。

### コマンドで

Linuxの場合だと
下記の様にopensslでコマンドが実行できる。

```bash
$ openssl s_client -connect example.com:443 < /dev/null 2> /dev/null | openssl x509 -text | grep Not
            Not Before: Sep 25 09:14:02 2014 GMT
            Not After : Oct 27 09:49:54 2017 GMT
Not Afterの後が有効期限

```
http://qiita.com/uemura/items/a3a0937f77494e62213c

Windows用のopensslバイナリがあるのでインストールしてみる。
http://www.digicert.ne.jp/howto/basis/openssl_on_windows.html
https://jp.globalsign.com/support/faq/177.html
下記のサイトの場所から``` Win32 OpenSSL v1.0.1L Light ``` をダウンロードして
http://slproweb.com/products/Win32OpenSSL.html
下記の場所にインストールされるようにしてみた。
``` C:\OpenSSL-Win32\bin ```

先ほどのLinuxのコマンドを Windows用に書き換える。
/dev/null　→ nul
grep → findstr

```bat
:: binディレクトリに移動 
cd C:\OpenSSL-Win32\bin
:: OPENSSL_CONFの環境変数をセットしないとアラートが出る。システム環境変数にセットでもOK
set OPENSSL_CONF=C:\OpenSSL-Win32\bin\openssl.cnf
:: Not Afterの後が有効期限
openssl s_client -connect example.com:443 < nul 2> nul | openssl x509 -text | findstr Not
            Not Before: Sep 25 09:14:02 2014 GMT
            Not After : Oct 27 09:49:54 2017 GMT

:: ファイルに出力の場合はリダイレクトを追加
openssl s_client -connect example.com:443 < nul 2> nul | openssl x509 -text | findstr Not > c:¥xxx¥xxxx.txt

```
このコマンドを定期的に実行してファイルを書き込み、後続の処理でファイルを読み込んで、アラートを投げれば良いか。


### PowerShellの場合
Powershell等でもできそうな気がするので、調べてみることにする。
※それっぽいのがあったので、後で調べる。
http://www.zerrouki.com/checkssl/
http://myitpath.blogspot.jp/2010/03/checking-ssl-cert-values-with.html

上記のサイトが正にその通りでした。
WEBサイトのSSL証明書の有効期限をチェックして、一定日数前になるとメールを出すPowershellのようです。

例外処理とか、標準出力の部分を除いて簡単にすると下のような感じ。

```ps1:checkssl.ps1

# WEBサーバ
$WebsiteURL="example.com"
# ポート
$WebsitePort=443
# コモンネーム
$CommonName="example.com"
# 閾値日数
$Threshold="15"
# 宛先メール
$MailTo="recipient@mail.com"
# メール件名
$MailSubject="$WebsiteURL - SSL証明書が $ValidDays 日で失効します"
#送信メール
$MailFrom="sender@mail.com"
#送信メールサーバ
$SmtpServer="mailserver.example.com"
#メール本文
$MailBody=@"
 WEBサイト "$WebsiteURL"のSSL証明書 は $ValidDays 日内に有効期限が切れます。
"@

# TCP/IP接続
$Conn = New-Object System.Net.Sockets.TcpClient($WebsiteURL,$WebsitePort) 
# SSL通信開始
$Stream = New-Object System.Net.Security.SslStream($Conn.GetStream())
# 証明書の検証を行う
$Stream.AuthenticateAsClient($CommonName) 
# 証明書の取得  
$Cert = $Stream.Get_RemoteCertificate()
# 証明書の失効日を取得
$ValidTo = [datetime]::Parse($Cert.GetExpirationDatestring())
# 現在から失効日までの日数を取得  
$ValidDays = $($ValidTo - [datetime]::Now).Days

if ($ValidDays -lt $Threshold)
{
# 残り日数が閾値日数未満の場合
    # 失効日を標準出力　
    Write-Host "証明書失効日: $ValidTo`n" -ForegroundColor Yellow
    # アラートメールを送信
    Send-MailMessage -To $MailTo -Subject $MailSubject -From $MailFrom -SmtpServer $SmtpServer -Priority High -BodyAsHtml $MailBody
}
else
{
    # 失効日を標準出力
    Write-Host "証明書失効日: $ValidTo`n" -ForegroundColor DarkGreen
}
$Conn.close()

```

## PHPの場合
下記の通り
http://qiita.com/suzuki86/items/a971a5cbbcd6179a2695
http://www.pahoo.org/e-soul/webtech/phpsec/phpsec-13-01.shtm
json4sパースベストプラクティス

## はじめに
json4sには結構色々JSONをパースする方法があり、どれ使ったら良いか分からなくなるので、自分なりのベストプラクティス書いてみた。突っ込み歓迎デス。

## Sample
以下では、最終的に

```scala
case class Hoge(x: Int, y: Int, z: Boolean)
```

みたいな出力したいが、実際のjsonが

```json
{"api_x": 1, "y": "2", "z": 1}
```

みたいなクソ実装になっているものを想定する。

## Best Practice
```scala
import org.json4s._

case class Hoge(x: Int, y: Int, z: Boolean)

object Hoge {
  implicit val format = DefaultFormats

  private case class RawHoge(api_x: Int, y: String, z: Int) {
    def build: Hoge = Hoge(api_x, y.toInt, z != 0)
  }

  def fromJson(obj: JValue): Option[Hoge] = 
    obj.extractOpt[RawHoge].map(_.build)
}
```

## まとめ
class生成をケチるな。

## 蛇足
変数名だけ変えたい場合は、extractOptする前にtransformFieldするのもアリだと思う。
chefspec で ruby_block 内をテストする

[chef の ruby_block 内でリソースを実行する](http://qiita.com/sonots/items/8ac33ce011bbfb210edd)で書いたようなレシピをテストしたい。こんなの。

```ruby:recipes/foo.rb
recipe = self

ruby_block "foo" do
  block do
    contents = File.read("/tmp/foo")
    recipe.log "foo" do
      message contents
    end
  end
end
```

chefspec は次のように書けば良い

```ruby:spec/recipes/foo_spec.rb
require 'chefspec'

describe 'cookbook-name::foo' do
  let(:chef_run) do
    ChefSpec::SoloRunner.new do |node|
    end.converge(described_recipe)
  end

  before do
    # File.read に stub をあてるにはこう
    allow(File).to receive(:read).and_call_original
    allow(File).to receive(:read).with("/tmp/foo") { "foo" }
    # ruby_block の中を実行するにはこう。
    # old_run_action は chefspec が挿げ替える前の chef の本物の run_action
    chef_run.ruby_block('foo').old_run_action(:run)
  end

  it do
    # いつものような expect(chef_run).to action_resource は利かない
    expect(chef_run.log("foo").message).to eql("foo")
  end

  it "いつものように expect(chef_run).to action_resource したい場合" do
    # chefspec が呼んでくれなくなっているので 自分で run_action を呼ぶ
    # action 名を指定しているので、action のテストにはならないかも
    chef_run.log('foo').run_action(:write)
    expect(chef_run).to write_log("foo").with(message: "foo")
  end
end
```


`execute#run_action(:run)` してしまえば、stub_command もあてられる
chef の libraries で attributes を設定する

ohai plugin の配布が面倒なので cookbook の libraries で attributes 設定したい

```ruby:libraries/my_mixin.rb
module MyAttributesMixin
  def initialize(*args)
    super(*args)
    node.default['my']['awesome']['attribute'] = 'yay!'
  end
end
Chef::Recipe.send(:prepend, MyAttributesMixin)
Chef::Resource.send(:prepend, MyAttributesMixin)
```

こんなかんじでできた。あってよかった `prepend`
rspec3 の stub でオリジナルを呼ぶ

ただのメモ。/path/to/file だけ stub してそれ以外はオリジナルを呼ぶにはこう

```rb
allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with("/path/to/file").and_return(false)
```
Git | Emoji を利用した Git の commit フォーマットの一例 #git #emoji

## :musical_score: 概要
Emoji を利用した Git の commit フォーマットの一例

## :musical_note: 前提
* Atom のコミットメッセージのルールを参考にしました
    * [Atom Git Commit Messages](https://atom.io/docs/v0.108.0/contributing#git-commit-messages)
* このフォーマットを広めよう、という意志はないのでフォーマットの是非について議論する気はない
* 所属組織および個人のプロダクトに関して、このルールでやってますよ、という一例
    * やってますよ、というよりはこれからやりますよ（2015/01/30 ～）
    * 試行錯誤するので、変化すると思う。この記事を最新に保てるか不明

## :musical_note: 利点
* 先頭の絵文字を見ただけでコミット種別を即判断できる
* コミット種別を分けることで、コミット粒度が適切になる
* コミットメッセージのフォーマット統一
* フォーマットを統一しておくことで増す利便性
    * 検索しやすくなる
    * 自動処理がしやすくなる

## :musical_note: 欠点
* 入力が面倒
    * Snippet で対応
        * 自組織＋個人の開発においては、エディタが統一されているので問題なし

## :musical_note: Rules

|Format|Desc|
|:--|:--|
|:new: add: input_your_summary|仕様追加|
|:up: modify: input_your_summary|仕様変更|
|:x: delete: input_your_summary|仕様削除|
|:recycle: refactor: input_your_summary|リファクタリング|
|:wrench: tool: input_your_summary|ツール等、人間以外によるコミット|
|:ballot_box_with_check: test: input_your_summary|テストコードの追加|
|:book: doc: input_your_summary|ドキュメント|
|:thumbsup: bump up: input_your_summary|バージョンアップ|
|:imp: dirty: input_your_summary|動かないバージョンのコミット等、仕方なく行うコミット|
|:question: other: input_your_summary|未分類。分類不可|

## :musical_note: Snippets
Sublime Text 2 のスニペットです。

<i class="fa fa-external-link" style="font-size:1em;"></i><i class="fa fa-github-square" style="font-size:1em;"></i> [git_commit_snippets](https://github.com/tbpgr/git_commit_snippets)

## :memo: 補足
* 仕様新規・仕様更新・仕様削除はあくまで仕様に対して分類する。振る舞いが変わらないならリファクタリング
* テストについては、プロダクトコードだけあるシステムに後からテストを追加するようなケースを想定
    * 新規機能の実装時にプロダクトコード・テストを一緒にコミットする場合は、仕様追加に分類
* ドキュメントは、 README や API ドキュメントなど
* バージョンアップは version ファイルの更新。この更新は version ファイルの更新以外と混在させない
* Dirty は、やむを得ず作業途中のコミットを行います、というようなケース
* 絵文字の直後に同等の意味を持つ英語を保持するのは、冗長かな？という話になった
    * しかし、慣れてる人以外にはあったほうが有益
    * どうせ Snippet で入力するので入力の手間的には気にならない

## <i class="fa fa-image" style="font-size:1em;"></i> コミットイメージ
実際に、上記の Snippet 作成時に Emoji Format の Commit 利用してみました。

![git_emoji_commit1.png](https://qiita-image-store.s3.amazonaws.com/0/43480/22d87464-3f8f-34ff-c047-b39eeaf7e1d3.png)

## :link: 関連記事
<i class="fa fa-external-link-square" style="font-size:1em;"></i> [Git の Commit Template + Subliem Text 2 の Snippet でコミットメッセージの作法を統一・効率化する](http://qiita.com/tbpgr/items/26dc9ede7bfbd093c924)
本当にあった怖い話〜IPアドレスが消えた〜

この前私の目の前で起こって何が起こったのか分からずパニックになったので書いておきます．
OS は Debian7 です．

今回以下のことをやりたいとします．

  * グローバルIP（別に仮想IPでも何でも同じ）を持っているサーバー A を諸事情によりサーバー B に移したい
  * サーバー B にまずテスト用の IP アドレスを付けて動作を確認したい
  * 動作確認をして問題がなければサーバー A の IP アドレスを乗っ取って対応完了としたい

ということで以下の作業を行いました．

  1. サーバー B の `/etc/network/interfaces` にテスト用の IP アドレスを付ける設定を書いた上で `ifdown -a && ifup -a`
    * 動作を確認
  2. サーバー B で`ip addr add` を使ってサーバー A の IP アドレスを付けて乗っ取る
    * [Linux - 仮想IPを付けたいそんな時 - Qiita](http://qiita.com/catatsuy/items/9c0ec02abfb3ee9f199a)
    * サーバー A で `ip addr del` を使ってサーバー A が持っている IP アドレスを消す
  3. テスト用に付けた IP を `ip addr del` を使って削除

__という作業を行うと乗っ取った IP アドレスもろとも該当 NIC から IP アドレスが消えます__

どうやら NIC に 2 つの IP アドレスを付けると最初に付けた IP アドレスが primary になり次に付けた IP アドレスが secondary になるらしく primary の IP アドレスを消すと secondary もろとも消えます．
今回テスト用の IP アドレスが primary になり，乗っ取った IP アドレスが secondary になったのでテスト用の IP アドレスを消すと同時に目的の IP アドレスまでも消えてしまったということでした．

またこれの非常に厄介なところは該当 NIC に付けられるネットワークの IP アドレスが全て消えてしまうのでこちらのネットワークのルーティングが消えてしまうというところです．
ルーティングが消えたことに気付かず，もう一度 IP アドレスを付けてもなかなか疎通せず，ここでパニックになってしまいました…

ということで今回の作業は以下の方法が正解みたいです．

  1. サーバー B の `/etc/network/interfaces` にテスト用の IP アドレスを付ける設定を書いた上で `ifdown -a && ifup -a`
    * 動作を確認
  2. テスト用の IP アドレスを `ip addr del` する
    * この時点でルーティングが消えているので要注意
  3. サーバー B で`ip addr add` を使ってサーバー A の IP アドレスを付けて乗っ取る
    * [Linux - 仮想IPを付けたいそんな時 - Qiita](http://qiita.com/catatsuy/items/9c0ec02abfb3ee9f199a)
    * send_arp の前に `ip route add` を打ってルーティングを付け直すことを忘れないこと
    * サーバー A で `ip addr del` を使ってサーバー A が持っている IP アドレスを消す
  4. テスト用に付けた IP アドレスを `ip addr del` を使って削除

という過程を踏むことで安全に切り替えることができます．

目の前で付けたはずの IP アドレスが消えた時は本当にパニックになりましたが落ち着いて IP アドレスを付け直してから疎通できなければルーティングを確認するというフローを踏めばよかった話で経験と確かな知識がものを言うなぁと改めて感じました．

ということで IP アドレス乗っ取りをする際は気を付けてください．
Vim に惚れるシーン（全てのソースファイルの uses 部に特定のモジュールを追加する）

# シーン 2

Delphi のソースコードの uses 部に、特定のモジュール参照を追加する必要があります。しかも、プロジェクト内の全てのソースに対して…。

プロジェクトの規模は、サブシステムが 7つ。機能数は 173機能で、ソースファイルの数でいうと… なんと **861 本**。

さて、どうしたものか…。

> 背景（本題とは少々脱線しています）
>
> 開発言語 Delphi を 2007 から XE4 にバージョンアップする案件。
> このバージョンアップでは、内部で扱う文字コードが ShiftJIS から Unicode に変更になったため、文字列を扱う関数群の互換性がなくなっているみたいで、影・響・大！
> 非互換な関数を使用している箇所は膨大で、すべて修正するのは非現実的だし、そもそもやりたくない。
> そこで、非互換を吸収するモジュール Compat2007 を作って、すべてのソースで uses してやるだけで、ソース内の関数を個別に修正することなく、互換性を維持することになったのです。

# どうしたい？

Delphi のソースは、次のようになっています。

```
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Mask, ComCtrls;

implementation
  :
```

interface 部の uses に Compat2007 を追加したいのです。
つまり、次のようになってほしいのです。

```
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Mask, ComCtrls, Compat2007;       // Compat2007 を追加しています

implementation
  :
```

注意しておきたいのは…

 - uses に書かれているモジュールの種類や数は、ソースファイル毎に異なる
 - interface 部の中には、uses 以外のブロックも存在し得る

ということです。

これを、全てのソースファイル **861本** の uses 部に対して、追加することになります。

# どうやって

一度に思考は働きません。順を追って考えていきましょう。

## まず、1つのソースファイルから

最初に、モジュールを追加したい箇所にマッチする正規表現を考えてみましょう。

```
/\vinterface\s*\n(.*\n){-}\s*uses\s*\n*(.*\n){-}.*\zs;\ze
```

簡単に補足すると…

 - `\v` で very magic を指定して、( ) や { } をエスケープ無しで入力しやすくしています。
 - `interface` 以降に出てくる最初の `uses` から `;` までを検索します。
 - 最後の `;` だけを置換対象にするために、`\zs` と `\ze` で囲みます。
 - `(.*\n)` で任意の行にマッチさせています。
 - `{-}` で最短マッチを指定しています。

これで、`interface` 部の `uses` にある最後の `;` が置換対象としてマッチされることになります。

次に、このマッチした箇所に `Compat2007` が追加されるように、置換を実行します。

```
:%s//, Compat2007;/
```

 - 直前に使用した正規表現をそのまま置換条件とするので、省略しています。
 - マッチした `;` を `, Compat2007;` に置換します。

これで、1つのソースファイルに対して、Compat2007 を追加できたことになります。
（以降の一括置換処理で二重に追加されてしまわないように、ここで実行した置換処理については、`u` で undo しておいてください）

## さあ、全てのソースファイルへ

いよいよ、全てのソースファイルへ適用する準備が整いました。

処理対象にしたいファイルを読み込みましょう。

```
:args **/*.pas
```

バックグラウンドで更新できるように、`hidden` を設定しておきます。

```
:set hidden
```

1つのファイルに対して実行した置換処理を、読み込んだファイル郡に対して、一括で実行します。（直前の置換処理を使用するので、省略できます）

```
:argdo %s
```

しばらく待っているだけで、全てのソースファイルに Compat2007 が追加されていきます。これは圧巻！

> 処理の経過が1行ずつ表示されて、1画面いっぱいになると処理が一時停止されます。
> 最後まで停止せずに処理を継続したい場合には、一時停止の状態で `G` を押してください。

あとは、ファイルの更新内容を確認して、問題なければ、一括保存しましょう。

```
:argdo w
```

# まとめ

複数行に渡る正規表現のマッチ＆置換処理と、`args`, `argdo` による一括処理で、**退屈なソース修正作業から開放** されるだけでなく、**大幅に修正工数を削減** することができました。

勿論、このソース修正を実行するスクリプト言語などを書いて対応する方法もあるでしょう。
しかし、コードを書くことなく、これだけの仕事を捌ききることができて、しかも試行錯誤しやすい環境を提供してくれる Vim には、やはり惚れてしまいますね。
JenkinsのGit Pluginでリポジトリからのプッシュ通知を受け取る

リポジトリのWebフック設定して叩くときとかの参考に


## Git Pluginインストール
JenkinsのGit Pluginはリポジトリからのプッシュ通知を手軽に受け取れる仕組みが用意されています。
[Git Plugin - Jenkins - Jenkins Wiki](https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin)

Jenkinsの管理 > プラグインの管理 > 利用可能タブ
から適当にフィルタ掛けてGit Pluginをインストールします。

## ポーリング設定
ポーリングというと定期的にジョブ実行するあれですが
Git Pluginでプッシュ通知受け取る際にもポーリングを有効にしておく必要があります。

![スクリーンショット 2015-01-31 2.08.05.png](https://qiita-image-store.s3.amazonaws.com/0/64633/5d203b86-e1dc-3ee3-2dc2-cf23ad82ffb9.png "スクリーンショット 2015-01-31 2.08.05.png")

`No schedules so will never run`と出ますが無視してok

## CSRF対策を無効にする
Git Pluginのバグな気もしますが、CSRF対策が有効になっていると以下のような403エラーが返ってきたりします。

```html
HTTP ERROR 403

Problem accessing /git/notifyCommit. Reason:

    No valid crumb was included in the request
```

Jenkinsの管理 > グローバルセキュリティの設定
でCSRF対策のチェックを外しましょう。(外していいのか疑問が残るが...)
![スクリーンショット 2015-01-31 2.41.40.png](https://qiita-image-store.s3.amazonaws.com/0/64633/bb97c9ff-4f99-ccd1-575b-175333b449d5.png "スクリーンショット 2015-01-31 2.41.40.png")


## リポジトリからのアクセスを通す
各環境などによると思いますが、例えばリポジトリが置いてあるIPからのアクセスを許可しとくとかそいういうのを忘れずに。

## いざ叩く

```
http://<Jenkinsサーバー>/git/notifyCommit?url=<リポジトリURL>
```

を適当に埋めて叩けば無事ジョブが実行されるはずです。
Webフックで叩く場合は上記URLを設定して下さい。

ちなみにGit Pluginのwikiでは
`http://<Jenkinsサーバー>/jenkins/git/notifyCommit?url=<リポジトリURL>`
となっていますが`/jenkins`はいらないようです。
MacでRmagickをインストール


> gem install rmagick

したくて

> brew install imagemagick

しただけだとダメで

> export PKG_CONFIG_PATH=/usr/local/Cellar/imagemagick/6.9.0-3/lib/pkgconfig

これ試してもダメで

> brew install pkg-config

pkg-configを入れたら通りました


# 参考
* https://github.com/rmagick/rmagick
* http://stackoverflow.com/questions/23684133/cant-install-rmagick-pkg-config-command-not-found
* http://qiita.com/hiroara@github/items/6b1c6c7257042a159cc9
elscreenの各タブに任意のバッファを一括設定する


elscreenを使ってバッファを開いたり閉じたりしてると
どのタブにどのバッファを開いてるかゴチャゴチャしてくるので
一旦リセットしたくて、各タブの定位置に任意のバッファをセットできる関数を作った。

alistに(スクリーン番号 . バッファ名)で登録しておくと関数実行に一括セットしてくれる

``` elisp
;; screenを定位置に設定する
(setq elscreen-custom-screen-alist
      '((0 . "Folder")
        (1 . "*twittering*")
        (2 . "todo.org")
        (3 . "*scratch*")
        (4 . "*scratch*")
        (5 . "*scratch*")
        (6 . "*scratch*")
        (7 . "*scratch*")
        (8 . "*scratch*")
        (9 . "*scratch*")))

(defun elscreen-set-custom-screen ()
  (interactive)
  (let ((screen-list (sort (elscreen-get-screen-list) '<))
        (current-screen (elscreen-get-current-screen)))
    (mapc (lambda (alist)
            (let ((screen-num (car alist))
                  (buffer-name (cdr alist)))
              (elscreen-goto (nth screen-num screen-list))
              (switch-to-buffer buffer-name))) elscreen-custom-screen-alist)
    (elscreen-goto current-screen)))

(global-set-key (kbd "<f8>") 'elscreen-set-custom-screen)
```
ソースコードやドキュメントを速攻で参照するctrlp-quickref.vimを作ってみた

今回始めてVimプラグインを作って見たので、宣伝も兼ねて投稿させていただきます。
この記事を読んだ人はぜひ一度使ってみて、何か意見や要望がある方はお知らせしてもらえると嬉しいです。

https://github.com/iwataka/ctrlp-quickref.vim

## イントロダクション

Vimでプログラムを書いていると、自分が使っているライブラリのソースコードを確認したくなったり、過去に書いたプログラムを参照したくなったり、その他PDFのドキュメントを開きたくなったりすることがよくあります。そういったときにVimの中から一瞬で目的のファイルを開くことができるような機能が欲しいと思い、プラグインを作成しました。[ctrlp-quickref.vim](https://github.com/iwataka/ctrlp-quickref.vim)という名前で、その名の通り、[CtrlP](https://github.com/kien/ctrlp.vim)の機能をベースにした拡張プラグインです。

## デモンストレーション

CtrlPのインターフェースを2回続けて利用します。
1回目は自分が登録したパスが表示され、そこから検索したいパスを選択します。
2回目は先ほど選択したパスを検索した結果が表示されるので、後は自分が開きたいファイルを選択するだけです!

https://raw.githubusercontent.com/iwataka/images/master/quickref.gif

## 使い方

このプラグインをインストールしたら、1回目のCtrlPのインターフェースに表示されるパスを登録しなければなりません。登録する方法は2つあり、1つは自分のvimrcに以下のようにg:ctrlp_quickref_paths変数を作成します。

    let g:ctrlp_quickref_paths = [
        \ '/directory1/library_or_something_else/src',
        \ '/directory2/*/src',
        \ '/directory3/*',
        " You want to exclude specified directory, put '!' at the head.
        \ '! /directory3/library_or_something_else/'
    ]

複数のパスを登録するためにワイルドカードが使用でき、除外したいパスがあれば"!"を先頭において指定することができます。

2つ目の登録方法は、~/.ctrlp-quickrefファイルを作成し、そこにパスを書き込むというものです。例としては以下のようになります。

    # Write
    # Some
    # Comments
    /directory1/library_or_something_else/src
    /directory2/*/src

    # Additional comment
    /directory3/*

    # You can also exclude specified directory by writing like this
    ! /directory3/library_or_something_else

gitignoreなどの構文を意識しています。

上の2つのうちのどちらかの方法でパスを登録したら、後は:CtrlPQuickRefコマンドを実行するだけです。CtrlPインターフェースが開き、自分が登録したパスの中から一つを選択します。再度CtrlPインタフェースが開き、選択したパスにおける検索結果が今度は表示されます。

### 例

例えば、./ctrlp-quickrefに以下のような内容を記述します。

    ~/.vim/bundle/*

すると、使っているVimプラグインのパスがすべて指定されたことになり、そのすべてのソースコードに簡単にアクセスすることが出来るようになります。Vimスクリプトを書いている時には便利だと思います。また、

    ~/projects/*

のように、自分のプロジェクトを保存しているディレクトリを指定すると、すべてのプロジェクトのソースコードやドキュメントを即座に見ることができます。


## コマンド

+ :CtrlPQuickRef

    CtrlPのインタフェースを開き、自分が登録したパスを選択肢として表示します。

+ :CtrlPQuickRefLastDir

    CtrlPを、自分が最後に選択したパスを引数として実行します。

+ :CtrlPQuickRefEdit

    自分のパスを登録しているファイル(デフォルトでは~/.ctrlp-quickref)を開きます
    。自分のvimrcに全て登録している場合は何も起こりません。

## オプション

+ ctrlp_quickref_readonly_enabled

    デフォルトではreadonlyフラグをつけてファイルを開きますが、この変数の値を0にするとreadonlyフラグをつけずにファイルを開くことができます。

+ ctrlp_quickref_open_extensions

    このリストに含まれている拡張子のファイルを開く場合は、Macではopen、Linuxではxdg-openで自動的に開かれます。デフォルトでは['html', 'pdf']となっています。

+ ctrlp_quickref_configuration_file

    パスを登録するファイルを指定します。デフォルトでは~/.ctrlp-quickrefです。

+ ctrlp_quickref_paths

    パスの登録をvimrc内で行う場合、この変数にリストとして登録します。

## 必要なプラグインなど

+ [ctrlp.vim](https://github.com/kien/ctrlp.vim)

+ xdg-open command (Linuxユーザのみ)

+ [ctrlp-py-matcher](https://github.com/FelikZ/ctrlp-py-matcher)

    これは不可欠ではありませんが、大きなプロジェクトなどに適用する場合には絞り込みが早くなるのでおすすめです。

+ [the_silver_searhcer](https://github.com/ggreer/the_silver_searcher)

    これも不可欠ではありません。CtrlPユーザの多くが使っているかもしれませんが、おすすめしておきます。
Vagrantのshare folderが遅い時はNFSを使うといいです

#概要
Vagrant内のcentos6でrailsの開発をしてました。

ソースを共有フォルダに置いて動作確認していたのですが挙動が
異様に重く、調べてみたらvagrantのデフォルトのファイル共有のせいでした。

NFSを利用したら早くなったのでその時のメモです。

#環境
* Mac OS X 10.9.5
* Vagrant 1.6.5
* VirtualBox 4.3.18

#内容

## 1. Vagrantfileの編集
ゲスト側の/vagrantをNFSでマウントするようにします。[*参考リンク](http://docs.vagrantup.com/v2/synced-folders/nfs.html)

```ruby:vagrantfile
  #--途中は省略--
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  #--途中は省略--
  config.vm.synced_folder ".", "/vagrant", type: "nfs"
  #--以後も省略--
end
```

## 2. sudoerを編集
このままでもOKですが、vagrant起動時に毎回マウントするため
パスワード聞かれます。聞かれないようにできるみたいです。

http://joemaller.com/3411/vagrant-nfs-shares-without-a-password/

mac上で下記shellを一度実行すれば聞かれなくなりました。
一応スクリプトを写経。

```bash:install_vagrant_sudoers.sh
#!/bin/bash
# Add Vagrant's NFS setup commands to sudoers, for `vagrant up` without a password
# Updated to work with Vagrant 1.3.x
 
# Stage updated sudoers in a temporary file for syntax checking
TMP=$(mktemp -t vagrant_sudoers)
cat /etc/sudoers > $TMP
cat >> $TMP <<EOF

# Allow passwordless startup of Vagrant when using NFS.
# https://gist.github.com/joemaller/6764700

Cmnd_Alias VAGRANT_EXPORTS_ADD = /bin/bash -c echo '*' >> /etc/exports
Cmnd_Alias VAGRANT_NFSD = /sbin/nfsd restart
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -E -e /*/ d -ibak /etc/exports
%staff ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD, VAGRANT_EXPORTS_REMOVE
EOF
 
# Check syntax and overwrite sudoers if clean
visudo -c -f $TMP
if [ $? -eq 0 ]; then
  echo "Adding vagrant commands to sudoers"
  cat $TMP > /etc/sudoers
else
  echo "sudoers syntax wasn't valid. Aborting!"
fi
 
rm -f $TMP

```

こんな結果になるはず

```
/tmp/vagrant_sudoers.ziY5C09b: parsed OK
Adding vagrant commands to sudoers
```

## 3. リロード
vagrantをリロードしましょう。
リロード後何も聞かれずに立ち上がればOKです。

```bash
vagrant reload
```

## 4. 結果
早くなりました。
ローカルで動かしてる時より若干遅いかな？くらいのレベルです。
（以前はrails起動ですら数分かかってました。）

#参考URL
http://docs.vagrantup.com/v2/synced-folders/nfs.html
http://webradar.info/2014/03/06/slowly-rails-in-vagrant/
https://gist.github.com/joemaller/6764700#file-install_vagrant_sudoers-sh
Groovyスクリプトを配布する1つの方法

#はじめに
Groovyでスクリプトを書いたのだけれど、どうやって配布しましょうか?というのはあると思います。今回は、GradleのApplicationプラグインを使った方法を考えてみます。

#GroovyスクリプトをGradleでビルドする
まず、GroovyスクリプトをGradleでビルドできる様にしましょう。
次の様なGroovyスクリプトを作成したとします。

```groovy:Hello.groovy
println "Hello ${args.join(',')}."
```

このファイルをプロジェクト(プロジェクトの親フォルダ名は`GroovyHelloScript`とします)の`src/main/groovy`に置いて、Gradleでビルドする様にします。

```gradle:build.gradle
apply plugin: 'groovy'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.0'
}
```

Groovy 2.4.0リリース記念(笑)ということで、Groovy 2.4.0を使う様にしています。

#Applicationプラグインを追加する
GradleのApplicationプラグインの良い所は、

* Windows/Mac/Linuxで実行可能なスクリプトを作成してくれる
* 実行に必要なjarをまとめてくれる

だと思います。

先ほどのGradleビルドスクリプトに、Applicationプラグインを追加してみましょう。

```gradle:build.gradle
apply plugin: 'groovy'
apply plugin: 'application'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.codehaus.groovy:groovy-all:2.4.0'
}

mainClassName = "Hello"
```

GradleのGroovyプラグインでビルドすると、Groovyスクリプトをコンパイルしたクラスファイルが作成されますので、このGroovyスクリプトのクラスを`mainClassName`に指定してあげれば実行できる筈です。

#実行可能なファイルを作成して、実行してみる
実行可能なファイルを作成してみます。
`gradle installApp`を呼ぶと、`build/install/GroovyHelloScript`に実行可能なファイルが作成されます。`bin`フォルダの実行スクリプトを`GroovyHelloScript Groovy Java Scala JRuby`の様にして実行すると、、、正しく実行されると思います。

#実行可能ファイルをZIPにまとめる
後は、配布できる様に実行可能ファイルをZIPにまとめます。
`gradle distZip`を呼ぶと、`build/distributions`にZIPファイル(`GroovyHelloScript.zip`)が作成されます。
このZIPファイルを配布して展開すれば、Javaが入っている環境で実行できる様になります。

#最後に
Groovyスクリプトを、GradleのGroovyプラグインとApplicationプラグインを使って配布できるという事が分かりました。
これを使えば、Groovyスクリプトで作成した、ちょっとしたツールを配布できますね。
Example 02: ボタンが押されている間、LEDを点ける


```example02.ino

const int LED = 13;
const int BTN = 7;

int val = 0;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BTN, INPUT);
}

void loop() {
  val = digitalRead(BTN);
  
  if (val == HIGH) {
    digitalWrite(LED, HIGH);
  } else {
    digitalWrite(LED, LOW);
  }
}
```

スイッチを押すとLEDが点く。

![16402474732_af15839ed8_z.jpg](https://qiita-image-store.s3.amazonaws.com/0/32195/38ebec7d-0add-ae9d-5151-096b0e9a9bcb.jpeg)

なんで抵抗をはさむのか分からない。

![16403386955_293b7efbf4_z.jpg](https://qiita-image-store.s3.amazonaws.com/0/32195/af4cf5a9-6677-1d4f-99ca-1838bf4ddabb.jpeg)

スイッチとLEDがつながってない。
むかし電池と豆球をつないだのとちがう。

![16215964780_332c3f0120_z.jpg](https://qiita-image-store.s3.amazonaws.com/0/32195/88505c90-4185-2c08-48eb-11ddd9728532.jpeg)

それからLEDと同時にARUDUINO上のLも点くんだね

## 写真を撮って分かったこと

* LEDが点いた写真もほしいな。
* 線はまとまりごとに同系色が分かりやすい。
* 線のカーブもきれいに曲げたい。

## 抵抗はなんでつけるんだろうね

考えてみよう

* 抵抗は7番とGNDあたりにある
* 抵抗は電流を小さくする
* スイッチ > 抵抗 > GND

もしかして抵抗がないと7番へ流れないのかな
水路とバルブの例えでイメージしてみた

* GNDはとても傾斜が強い排水溝
* とても流れやすい
* 水門でせきとめられると
* あふれだし７番へ流れ出す

抵抗はずしてみよう。
つぶれないか心配。

<iframe width="560" height="315" src="https://www.youtube.com/embed/yJcxMYmd0ww" frameborder="0" allowfullscreen></iframe>
DNSのキャッシュをクリアする

hosts書き換えたのに変更前のIPを参照していて困った時に使えるコマンド。
これでもう`Ctrl+F5`の連打はしなくていいｗ

## for Linux
```bash
$ /usr/sbin/nscd -i hosts
```
`nscd`：**N**ame **S**ervice **C**ache **D**aemon(ねーむさーびすきゃっしゅでーもん)
`-i --invalidate=TABLE`：Invalidate the specified cache(指定されたキャッシュを無効にする)
→　つまり、このコマンドは「hostsのキャッシュを無効にする」という意味
`ping`などで参照先の確認が出来る。

## for Windows
```bash
> ipconfig /flushdns
```
「DNSリゾルバーキャッシュを破棄します」(`--help`より)
`ipconfig /displaydns`で確認出来る。
Rails入門を終えたので今後の課題メモ

[Rails入門](http://ruby.studio-kingdom.com/rails/guides/getting_started)を読んで、CRUDアプリを作ってみました。
入門ガイドで使われるアプリケーションなので、当然なのですが、実際の業務で使うにはちょっと不便な感じです。
業務アプリでお客様からよく出される要求に対して、Railsではどうやって実装（または設計）するのがいいかを考えたり調べたりしたら、勉強になるんじゃないかなと思い立ち、WEBアプリケーションの要件でよくあるものを並べてみました。

## 検索

* 条件で検索したい -> [Railsで条件検索](http://qiita.com/ishidam/items/d8cf41d2c6e49c2777bd)
* [部分一致とか日付の範囲で検索したい](http://qiita.com/ishidam/items/4ca054a2204c174003b9)
* 複数の条件で検索したい -> [Railsで条件検索](http://qiita.com/ishidam/items/d8cf41d2c6e49c2777bd)
* [関連するモデルの条件で検索したい](http://qiita.com/ishidam/items/7dba557d764362a828ff)
    * [指定した全ての要素をhas_many関連先に持つ条件の書き方](http://qiita.com/ishidam/items/4e70010c0e11399c3404)

* 検索結果をページ送りにしたい
    * -> [kaminari](https://github.com/amatsuda/kaminari)を使う
* 検索結果の並び順を指定したい
    * [ransack](https://github.com/activerecord-hackery/ransack)のヘルパーメソッドでできる
* 条件に該当した件数を表示したい
    * `@models.size`
* 検索結果をCSV出力したい
* よく使う検索条件を登録して呼び出せるようにしたい
* 画面遷移で検索結果が消えないようにして欲しい

## 登録

* 登録時に項目間の関連チェックしたい
* 登録する前に確認画面を出して欲しい
* CSVファイルから一括登録したい
* 悪い人が自作フォームで登録できないようにして欲しい
* 登録ボタンを連打しちゃう人がいても大丈夫なようにして欲しい
* 選択式の項目で親子関係があるものは絞り込んで欲しい

## 更新

* 変更した項目だけを更新して欲しい
* 変更した履歴を残したい
* 誰が変更したのか分かるようにしたい
* 他の人が変更してたら教えて欲しい
* 検索結果に対する一括操作がしたい

## 削除

* 削除は削除フラグを立てる方式にしたい

## その他

* 件数とか合計を集計したい
* 集計したら帳票としていい感じに出力したい

## 要件以外の課題

* たくさんある小さなマスタを共通化したい
* マスタの初期データを一括登録したい
* 開発用のデータをCSVから一括で登録したい


つらつらと挙げていたら結構な数になってしまいました。書いてるうちにイヤな思い出ばかり蘇ってきます。。

他にもあると思うので思いついた方はコメントで教えて欲しいです。
jQueryとBootstrapのCDN(Content Delivery Network)


###多くのサイトで利用しているCDN読み込みだとクライアント側でのキャッシュの効果が見込めるのでそれぞれ一択で


###jQuery
https://developers.google.com/speed/libraries/devguide#jquery

```
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
```

###jQuery Mobile
https://developers.google.com/speed/libraries/devguide#jquerymobile

```
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.css" />
```

```
<script src="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.js"></script>
```


###jQuery UI
https://developers.google.com/speed/libraries/devguide#jqueryui

```
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css" />
```

```
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
```

###Bootstrap
http://www.bootstrapcdn.com/

```
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
```

```
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
```

##CDNが停止していたらローカルのファイルを読み込む設定例

```
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<script>window.jQuery || document.write('<script src="js/jquery-ui.min.js"><\/script>')</script>
```

####もしCDNにアクセスできなければ、ローカルのファイルを読みこむ
古いDebian etchやlennyの「GHOST」（CVE-2015-0235）脆弱性対策

新しいめのOSであれば

```
yum update glibc
```

とか

```
apt-get install libc6
```

して再起動したらOK。

でもDebianの4(ethc)や5(lenny)はサポートが切れてるので修正パッチはこない。
そんな古いDebianサーバでアップデートの必要があったので検証。

##パッチの中を見る

squeeze-ltsでは修正のパッチがきており「2.11.3-4+deb6u4」で対策済みとの事なので
このパッケージのgethostbyname()関連のパッチを見た。

http://sources.debian.net/data/main/e/eglibc/2.11.3-4+deb6u4/debian/patches/any/cvs-gethostbyname.diff

なんかそんなに複雑な修正ではなさそうなので、
etchやlennyのリポジトリで最新(って言い方もおかしいけど・・・)の
glibcのパッケージソースを取得し、上記パッチを追加してdebパッケージを再作成。
作成したパッケージをインストールすれば対策できるんじゃないかということでやってみました。

##Debian etchでの対策
事前にetchのアーカイブリポジトリを`/etc/apt/sources.list`に追加しておきます。

```
deb http://ftp.riken.jp/Linux/debian/debian-archive/debian/ etch main
deb-src http://ftp.riken.jp/Linux/debian/debian-archive/debian/ etch main
```

etchでの最新のlibc6のソースを取得

```bash
cd /root
apt-get update
apt-get install libc6
apt-get install dpkg-dev
apt-get build-dep libc6
apt-get source libc6
apt-get install devscripts
```

とってきたdebパッケージにパッチ（`cvs-gethostbyname.diff`）を追加して
パッチ名を`series`に追加

```bash
cd /root/glibc-2.3.6.ds1/debian/patches/all
wget http://sources.debian.net/data/main/e/eglibc/2.11.3-4+deb6u4/debian/patches/any/cvs-gethostbyname.diff
echo "all/cvs-gethostbyname.diff -p 1" >> /root/glibc-2.3.6.ds1/debian/patches/series
```

パッケージのバージョンを設定

```
dch
```

パッケージ作成

```bash
cd /root/glibc-2.3.6.ds1/
dpkg-buildpackage -us -uc
```

作成したパッケージインストール

```bash
cd /root
dpkg -i libc6_2.3.6.ds1-13etch10_i386.deb
```

チェックプログラムを実行してみて確認(作成方法は割愛)

```
./ghost
not vulnerable
```

##Debian lennyでの対策

lennyの場合もほとんど一緒です。
事前にlennyのアーカイブリポジトリを`/etc/apt/sources.list`に追加しておきます。

```
deb http://ftp.riken.jp/Linux/debian/debian-archive/debian/ lenny main
deb-src http://ftp.riken.jp/Linux/debian/debian-archive/debian/ lenny main
```

lennyでの最新のlibc6のソースを取得

```bash
cd /root
apt-get update
apt-get install libc6
apt-get install dpkg-dev
apt-get build-dep libc6
apt-get source libc6
apt-get install devscripts
```

とってきたdebパッケージにパッチ（`cvs-gethostbyname.diff`）を追加して
パッチ名を`series`に追加

```bash
cd /root/glibc-2.7/debian/patches/all
wget http://sources.debian.net/data/main/e/eglibc/2.11.3-4+deb6u4/debian/patches/any/cvs-gethostbyname.diff
echo "all/cvs-gethostbyname.diff -p 1" >> /root/glibc-2.7/debian/patches/series

```

パッケージのバージョンを設定

```
dch
```

パッケージ作成

```bash
cd /root/glibc-2.7/
dpkg-buildpackage -us -uc
```

作成したパッケージインストール

```bash
cd /root
dpkg -i libc6_2.7-18lenny8_i386.deb
```

チェックプログラムを実行してみて確認(作成方法は割愛)

```
./ghost
not vulnerable
```
serverspecのpackageリソースはrpmコマンドでテストをする


Vagrant上の仮想マシンにserverspecでテスト環境を整えようと思った時に詰まったメモ。

## 前提
VagrantfileのあるChefリポジトリのトップディレクトリで`$serverspec-init`により初期ファイルを出力。結果は以下のとおり。

```
$ tree spec/
spec/
├── default
│   └── sample_spec.rb
└── spec_helper.rb
```

そして`rake spec`が実行可能な状態。

## 詰まったところ

```spec/default/sample_spec.rb
require 'spec_helper'

describe package('vim') do
    it { should be_installed }
end
```

仮想マシン上で`yum install vim`して、ホストマシン上で`rake spec`。これでテストが通るはず、と思ったら・・・

```
Failures:

  1) Package "vim" should be installed
     On host `default'
     Failure/Error: it { should be_installed }
       expected Package "vim" to be installed
       sudo -p 'Password: ' /bin/sh -c rpm\ -q\ vim
       package vim is not installed

     # ./spec/default/sample_spec.rb:4:in `block (2 levels) in <top (required)>'
```

あれ、通らない・・・。

ご丁寧にも情報が情報が充実していて、テストに使用したコマンドが出力される。

`sudo -p 'Password: ' /bin/sh -c rpm\ -q\ vim`と表示されているように、テストにrpmコマンドを利用している。どうやらyumでインストールしたpackageはこのままではテストされないようだ。


## 解決策

しょうがないので、`yum install vim`で呼び出されてrpmからインストールされるものを確認して、直接testすることにする。

```ゲストマシン上
$ rpm -qa | grep vim
vim-common-7.2.411-1.8.el6.x86_64
vim-enhanced-7.2.411-1.8.el6.x86_64
vim-minimal-7.2.411-1.8.el6.x86_64
``` 

grepでしか調べてないけど、`vim-common`と`vim-enhanced`と`vim-minimal`の3つが入っていればいいということにする。個々のpackageの違いや役割は詳しく知らないがとりあえず放っておく。

以下のようにテストスクリプトを書き直す。


```spec/default/sample_spec.rb
require 'spec_helper'

%w{vim-common vim-enhanced vim-minimal}.each do |vim|
    describe package(vim) do
        it { should be_installed }
    end
end
```

これできちんとテストができました。

```
Package "vim-common"
  should be installed

Package "vim-enhanced"
  should be installed

Package "vim-minimal"
  should be installed

Finished in 0.69752 seconds (files took 6.01 seconds to load)
3 examples, 0 failures
```

このように毎回rpmを調べて複数packageのテストを行うのはちょいと面倒だけれども、今までyumの下のレイヤーのrpmに気を配ったことがなかったので、よい勉強の機会ということにしてこれからテストを書くことにする。
Knockout.jsでimgタグsrc属性にデータバインドする時のアンチパターン


## 不完全な状態でsrcが解決されてしまい404エラーが発生する

img[src]にデータバインドした時にエラー出まくったので。

### ViewModel

```
var viewModel = {
	filename: ko.observable()
};
ko.applyBindings(viewModel);
```

この後ajaxなりで`filename("myimage.jpg")`などが入ってくるとする。

### HTML

```
<img data-bind="attr: {src: '/static/img/' + filename()}">
```

上記のように`{src: "文字列"}`渡してしまうと、即以下のようなHTMLとして反映されてしまうので404エラーが発生する。

```
<img src="/static/img/undefined">
```

## 404回避

これを回避するには `filename('/static/img/myimage.jpg')` とパス情報などの文字列も含めて同時に渡すか
以下のように書いて`filename()`に値が入るまでHTMLに反映させないなどの手があるっぽい。

```
<img data-bind="attr: {src: filename4() ? '/static/img/' + filename4() : ''}">
```

（もっとスマートな方法あったら教えて下さい）



## 追記

コメント欄にてカスタムバインディングを使う例を教えていただきました。これが一番スマートだと感じます。
MKGaruさんありがとうございます！
RailsでISO8601

RailsでAPIを作るとき、日付や時間のフォーマットはi18nでローカライズするのではなく、iso8601で扱いたいことがあると思います。

そんなときどうすれば良いのか調べてみました。

# 入力

iso8601に準拠した文字列をそのまま代入すると、勝手に変換してくれます。

```
user.birth_date = '1995-01-01'
```

# 出力

config/initializers/datetime_formats.rb を作成し、デフォルトのフォーマットをiso8601にする。

```config/initializers/datetime_formats.rb
Date::DATE_FORMATS[:default] = Date::DATE_FORMATS[:iso8601]
Time::DATE_FORMATS[:default] = Time::DATE_FORMATS[:iso8601]
```

# まとめ

意外と簡単だった。

# 参考

- [Custom Formats for DateTime](http://robots.thoughtbot.com/custom-formats-for-datetime)
tbpgr が利用している Chrome Extension 一覧 #chrome_extension

chrome_extension

# tbpgr が利用している Chrome Extension 一覧 #chrome_extension
## :musical_score: 概要
:smirk_cat: tbpgr が利用している Chrome Extension 一覧 です。

:recycle: 随時更新予定

## :musical_note: 一覧
|ToolName|Memo|
|:--|:--|
|[esa notifier](https://chrome.google.com/webstore/detail/esa-notifier/hgfdalcpdmhcdofmoafhmfjhgopohnfc?utm_source=chrome-app-launcher-info-dialog)|esa の通知|
|[ImproveTagList for Qiita](https://chrome.google.com/webstore/detail/improvetaglist-for-qiita/oeicblbkfdbhicfmfaplefglpkjmbblj?utm_source=chrome-app-launcher-info-dialog)|Qiita のユーザーページの円グラフ横のタグ名をリンクに変更し、該当タグ＋該当ユーザーでの検索を行う|
|[Isometric Contributions](https://chrome.google.com/webstore/detail/isometric-contributions/mjoedlfflcchnleknnceiplgaeoegien?utm_source=chrome-app-launcher-info-dialog)|GitHub の Contributions を 3D 表示する|
|[Markdown Linker](https://chrome.google.com/webstore/detail/markdown-linker/kgadgjmlofjccpefhdagbonmohjknlll?utm_source=chrome-app-launcher-info-dialog)|Web ページのリンクを Markdown のリンクとしてコピー|
|[pplog ( ˘ω˘)ﾉ"Y☆Yヾ(˘ω˘ ) twitter](https://chrome.google.com/webstore/detail/pplog-%CB%98%CF%89%CB%98%EF%BE%89y%E2%98%86y%E3%83%BE%CB%98%CF%89%CB%98-twitter/hcllnjgfjhmjlcnophepcicggnpophfn)|pplog と Twitter のユーザーの相互移動機能|
|[qiita ( ˘ω˘)ﾉ"Y☆Yヾ(˘ω˘ ) twitter](https://chrome.google.com/webstore/detail/qiita-%CB%98%CF%89%CB%98%EF%BE%89y%E2%98%86y%E3%83%BE%CB%98%CF%89%CB%98-twitter/acoblfmcdfihphocnnbcokdchegphalf)|Qiita と Twitter のユーザーの相互移動機能|
|[Qiita お知らせ](https://chrome.google.com/webstore/detail/qiita-notifications/lfaggijcindkbihlopcogjlihmpdpdaa?utm_source=chrome-app-launcher-info-dialog)|Qiita の通知|
|[Quick-Notifier for Trello](https://chrome.google.com/webstore/detail/quick-notifier-for-trello/gdefhppjmapmooojcbdbbpgakejfnhec?hl=ja)|Trello の通知|
|[Show Title Tag](https://chrome.google.com/webstore/detail/show-title-tag/pkbffbhglicfngmppdlpmpblfgnkdgio?utm_source=chrome-app-launcher-info-dialog)|タイトルが長く、タブからはみ出ている場合のために画面右下にタイトルを表示してくれる|
|[soku_qiita](https://chrome.google.com/webstore/detail/sokuqiita/pdbkaalghgacoghbclifkbklgeoaneil)|Qiita のユーザー・タグ指定検索をマウスを使わずに素早く操作します|
|[Tab Ahead](https://chrome.google.com/webstore/detail/tab-ahead/naoajjeoiblmpegfelhkapanmmaaghmi?utm_source=chrome-app-launcher-info-dialog)|Tab を CUI でインクリメンタル検索して移動|
|[Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?utm_source=chrome-app-launcher-info-dialog)|GreaseMonkey Script の管理ツール。Store に公開されていないスクリプトを使うにはこれが必要|
|[はてなブックマーク GoogleChrome 拡張](https://chrome.google.com/webstore/detail/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%83%E3%82%AF%E3%83%9E%E3%83%BC%E3%82%AF-googlechrome-%E6%8B%A1%E5%BC%B5/dnlfpnhinnjdgmjfpccajboogcjocdla?utm_source=chrome-app-launcher-info-dialog)|GreaseMonkey Script の管理ツール。Store に公開されていないスクリプトを使うにはこれが必要|
Scssのcolor palette 管理についてのメモ


今までなんとなしに色管理とかカラーパレットは

```scss
$color-red : #fe0000;
$color-red-dark : #ce0000;
$color-blue : #000ef;
$color-blue-dark : #000ec;
```
てな具合で十分かなと思っていたけど最近はmapとかあるしその辺使った管理とかどうかなとか思ったらよさ気なのがあったのでまとめ。

- http://erskinedesign.com/blog/friendlier-colour-names-sass-maps/
- http://maketea.co.uk/2014/07/21/managing-relationships-between-colours-with-sass.html

# mapを使ったいい感じのやり方
まず最終的なアウトプットから。

```scss
// パレットの定義
$color-palette :( 
  red : (
    base : #ff0000,
    dark : #ffcccc
  ),
  blue : (
    base : #0000ff,
    light : #00bbff,
  )
) !default;

// color(色系統, トーン)
@function color($color, $tone){
  @return map-get(map-get($color-palette, $color), $tone)
}
```

Sample usage

```sass
.red-button{
	background  : color(red);
}

.dark-blue-button{
	background  : color(blue, light);
}
```
関数名はまあなんでも良さげではあるけど`color()`とか`palette`とかがあるようだった。

こうすることでこれなにが利点なのか？

### 利点1：色ごとのセレクタ動的生成
というとmapなので繰り返しができること。

例えばstyleguide用に各色のサンプル出したいならこんな感じだし

```scss
// 一覧サンプル出力
@each $name, $palette in $color-palette {
  @each $tone, $code in $palette {
    .sample-color-palette-#{$name}-#{$tone}{
      background : color($name, $tone);
      .black-text{ color : #000 };
      .white-text{ color: #fff };
    }
  }
}
```

ボタンを特定の色で作りたかったらこんな感じとか

```scss
// redとblueのボタンを自動生成
@each $color in red, blue{
  .button-#{$color}{
    color: white;
    background : color($color);
  }
}

// 実際には色名をクラスには付けないのでこんな用途になりそう
$level-map :(
  error : red,
  warn : yellow,
  info : blue
);
@each $level, $color in $level-map{
  .log-#{$color}{
    color: white;
    background : color($color);
  }
}
```

### 利点2:色生成の隠蔽
今回paletteはmapで管理したけども、将来リファクタで整理されて、`lighter`などの色関数を使えばよくね？みたいなことになった時に影響少なめで変更できそう（と思ったけどあんまりこれが活きるパターンはないな・・・）


## 欄外：なんでこんなことを思ったのか

そもそも実は

```scss
$color-map : (
	red : #ff0000,
	blue : #0000ff
);
@each $color, $code in $color-map{
	$color-#{$color} : #{$code}
	.sample-#{$color} :{
		background : $color-#{$color}
	}
}
```
のように動的にvariableを展開するようなのとかできないのかなーと思って調べていたら似たようなことをして詰まっている人を見つけた

https://github.com/sass/sass/issues/1450

このissueでも上記のようなやり方が紹介されていて、提唱者は問題なかったといっている。めでたしめでたし。