OmniAICreator/Qiita-1.07M huggingface dataset:
Google Apps ScriptでShift_JIS変換したcsvをメール添付送信

Google Apps Script で2次元配列のデータを csv に変換してメールで送る方法を調べてみました。

## 前提

* 2次元配列データをcsvに変換する
* Shift_JIS にエンコードし添付ファイルでメール送信


## コード

```js:csv.gs
function sendMail() {
  var data = [
    ["あああ","いいい","ううう"],
    ["aaa","bbb","ccc"]
    ];
  var csvFile = convertValuesToCsvFile_(data)
  var blob = Utilities.newBlob("", 'text/comma-separated-values', 'mycsv.csv');
  blob.setDataFromString(csvFile, "Shift_JIS");

  var mailTo = "your@email.here";
  var subject = "CSV file";
  var body = "CSV file";
  var options = {attachments: [blob]};
  MailApp.sendEmail(mailTo, subject, body, options);
}

function convertValuesToCsvFile_(data) {
  try {
    var csvFile = undefined;

    // Loop through the data in the range and build a string with the CSV data
    if (data.length > 1) {
      var csv = "";
      for (var row = 0; row < data.length; row++) {
        for (var col = 0; col < data[row].length; col++) {
          if (data[row][col].toString().indexOf(",") != -1) {
            data[row][col] = "\"" + data[row][col] + "\"";
          }
        }

        // Join each row's columns
        // Add a carriage return to end of each row, except for the last one
        if (row < data.length-1) {
          csv += data[row].join(",") + "\r\n";
        }
        else {
          csv += data[row];
        }
      }
      csvFile = csv;
    }
    return csvFile;
  }
  catch(err) {
    Logger.log(err);
    Browser.msgBox(err);
  }
}
```

### 補足

`Blob#setDataFromString(str, charset)`を使うと文字列を文字コード指定でセットできるので、まず `Utilities.newBlob("", 'text/comma-separated-values', 'mycsv.csv');` で空の Blob を作ってます。

このコードでgmailからdownloadしたところ問題ありませんでした。

## 参考

* [Tutorial: Interacting With Your Docs List#section3](https://developers.google.com/apps-script/articles/docslist_tutorial?hl=ja#section3)
* [GASで文字コード指定してファイルを書き出す](http://qiita.com/jsoizo/items/948e23231417d203eefa)
AWS LambdaをJavaから使ってみる

「[AWS LambdaをRubyから使ってみる](http://qiita.com/Keisuke69/items/40bab85fa2a6ba5b257f)」のJava版です。
コードの部分がJavaに変わった以外に特に違いはありません。
なので、[元記事](http://qiita.com/Keisuke69/items/40bab85fa2a6ba5b257f)も参照してもらえるといいかと思います。

AWS LambdaはS3やKinesis、DynamoDBのイベントをトリガーにJavaScript/Node.jsで書かれたコードスニペットを実行するというサービスです。
イベントの実行元として上記以外にAPIからの直接実行も可能となっているので今回はAWS SDK for Javaを利用してこれを試してみます。

Lambda functionは前回と同様のものを「invoke-from-sdk」という名前であらかじめ作成しておきます。実行される処理も前回と同様で渡されたパラメータ（JSON形式）のkey1というキーの値を読み取ってコンソールに出力します。

Java側のプロジェクトはMavenプロジェクトとして構成しています。
サンプルコードはgithub上に置いておきました。

https://github.com/Keisuke69/lambda-java-sample

まずはpom.xmlにAWS SDKを追加します。今回は面倒だったのでフルで依存関係を設定していますが、サービス単位とかで細かく指定することも可能です。例えばaws-java-sdk-dynamodbを指定することも可能です。
というわけでpom.xmlの`<dependencies></dependencies>`に追加します。

```xml:pom.xml
  <dependencies>
--省略--
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk</artifactId>
        <version>1.9.7</version>
    </dependency>
  </dependencies>
```

続いてコードです。
今回はこんな感じです。

```java:Sample.java
package org.sample.lambda;

import com.amazonaws.services.lambda.AWSLambdaClient;
import com.amazonaws.services.lambda.model.InvokeAsyncRequest;
import com.amazonaws.services.lambda.model.InvokeAsyncResult;

public class Sample {
	public static void main(String[] args){
		Sample sample = new Sample();
		sample.invokeLambdaFunction();
	}
	
	private void invokeLambdaFunction(){
		AWSLambdaClient lambda = new AWSLambdaClient();
		
		InvokeAsyncRequest invokeAsyncRequest = new InvokeAsyncRequest();
		invokeAsyncRequest.setFunctionName("invoke-from-sdk");
		invokeAsyncRequest.setInvokeArgs("{\"key1\":\"from java\"}");
		
		InvokeAsyncResult invokeAsyncResult = lambda.invokeAsync(invokeAsyncRequest);
		int status = invokeAsyncResult.getStatus().intValue();
		
		if(status == 202){
			System.out.println("success");
		}
	}
}
```
処理内容としては前回と同様です。
Lambdaのクライアントクラスとして処理をブロックする通常のAWSLambdaClientとノンブロッキングなAWSLambdaAsyncClientの2種類がありますが今回はサンプルなのでAWSLambdaClient（ブロックする方）を使っています。
従ってレスポンスが返ってくるまでwaitすることになります。

あと、今回はちゃんと例外処理をしていませんがinvokeAsyncメソッドはいくつかRuntimeExceptionを発生させるので実際にはtry~catchで囲むなど適切に処理してください。

実行したら一応CloudWatchの画面で確認してみます。

![Screen Shot 2014-11-25 at 4.59.53 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/b2fca9cf-d56a-5ae6-6b21-85876a9256e7.png)

はい、ちゃんと実行できてますね。
Rubyほど簡単ではないですがこのようにJavaからもLambda functionを呼び出せます。

**免責
こちらは個人の意見で、所属する企業や団体は関係ありません。**
html5 <input type='file' … で、選択可能なファイルを指定する

accept属性を指定する

●MIME指定

```
<input type='file' accept='image/jpeg'>
```

●形式問わない場合

```
<input type='file' accept="image/*">
```

●拡張子指定

```
accept=".jpg,.gif,.png,image/gif,image/jpeg,image/png"
```
Google App Engine にて goapp によるデプロイに失敗する場合の対策

例えば GAE に go アプリケーションをデプロイするチュートリアルをやっている途中などに
https://cloud.google.com/appengine/docs/go/gettingstarted/uploading

デプロイの際、認証に失敗してしまいます。

# 2段階認証あり

google アカウントを2段階認証に設定している場合とそうでない場合で、エラーメッセージが変わります。

```
Use an application-specific password instead of your regular account password.
See ...
However, now the recommended way to log in is using OAuth2. See
...
```

## 対策(OAuth)

参考:
https://cloud.google.com/appengine/docs/go/tools/uploadinganapp#Go_Password-less_login_with_OAuth2

```
goapp deploy --oauth
```

にてブラウザが起動し、2段階認証のフローが終了すればデプロイされます。

## 対策(アプリパスワード)

短時間有効なパスワードを生成して、それでログインします。

参考:
http://www.google.com/support/accounts/bin/answer.py?answer=185833

ここから新しいパスワードを作成します。
https://security.google.com/settings/security/apppasswords
名前は何でも良い、、んじゃないですかね。

パスワードが生成されましたのでメモして、

```
goapp deploy
```

でメールアドレスはいつもの、パスワードはgmailなどのログインに使う物では無く、生成された方を使います。

# 2段階認証なし

```
% goapp deploy .
Email: 
Password for hoge@gmail.com:
Invalid username or password.
```

ユーザ名が違うよという警告と、gmail 宛に、「ログイン試行をブロックしました」みたいなメールが届くかと思います。

## 対策(セキュリティを下げる)

安全性の低いアプリのアクセス
https://www.google.com/settings/security/lesssecureapps

を有効にすることで、gmailなどのログインに使うパスワードでログインできます。
【Apache】Apacheをインストールしたら知っておきたい設定項目


## 前提

CentOS6.5で動作確認をしています。
初心者を想定して記述しているドキュメントとなっています。
開発用サーバとして動かすこと前提に記述しています。


## Apacheのインストールと初期設定

### Apacheのインストール

	# yum install httpd httpd-devel -y  # Apache(httpd)をインストール

### Apacheの起動

	# service httpd start       # Apacheを起動

### 自動起動の設定

	# chkconfig httpd on        # Apacheの自動起動を設定


## Apacheの設定ファイルを確認

### Apacheの設定ファイルのオリジナルをバックアップ

	# cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.origin	# httpd.conf.originという名前でオリジナルの設定ファイルをバックアップ


### ドキュメントルートの設定

ドキュメントルートとは、ブラウザからアクセスした時にApacheがまずプログラムファイルを探しに行くディレクトリのこと。
デフォルトの設定では292行目になってます。

	DocumentRoot "/var/www/html/"


### ディレクトリディレクティブの設定


	<Directory "/var/www/html">

		
	</Directory>



### ディレクトリインデックス
設定例：

	DirectoryIndex index.html index.php


### サーバシグネチャの設定（セキュリティ的な観点から）
推奨設定：

	ServerSignature Off
[Ruby 2.x] Chatworkに定期投稿する

# はじめに

以下の記事をなぞってみたメモになります。

- http://dev.classmethod.jp/client-side/language-client-side/use-chatwork-api/

#やりたいこと

chatworkを普段使っているので、毎月の定例報告などを流したい。

- 経費精算締め切り
- 朝会など定例会開始の呼びかけ

# Chatwork API 利用申請

こちらから申請をします。

- http://developer.chatwork.com/ja/index.html

![Screen Shot 2014-11-25 at 15.53.44.png](https://qiita-image-store.s3.amazonaws.com/0/18705/a1100bcd-23f2-55b9-7b16-875cee1bc275.png)

![Screen Shot 2014-11-25 at 15.57.27.png](https://qiita-image-store.s3.amazonaws.com/0/18705/16c177f2-d873-a33e-7bf2-bd0a8c326f91.png)


# Chatwork API 獲得

申請をするとすぐにmailが飛んできたりして、使えますよ〜となりました。
ChatworkのPersonal Settingsの中にAPI発行タブが出てくるので、そこからAPIを獲得します。

![Screen Shot 2014-11-25 at 15.55.10.png](https://qiita-image-store.s3.amazonaws.com/0/18705/2b766923-ce85-7f1f-a871-d092b737f908.png)


# Rubyコードを書きます。

とりあえず、ルームの情報を取ってくる

```rb
require 'rss'
require 'net/https'
require 'json'

CW_API_TOKEN = "API"

def request_api
  uri = URI('https://api.chatwork.com/v1/rooms')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true # HTTPSでエンドポイントへ通信が必要です
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE 

  header = { "X-ChatWorkToken" => CW_API_TOKEN } #api_tokenを、headerのX-ChatWorkTokenにセットすることが必要です
  body = nil

  res = http.get(uri, header) #あとはGETします
  puts JSON.parse(res.body)
end

request_api
```

メッセージを送りたいルームのRoom IDをメモしておきます。

# ルームにメッセージを送る

```rb
require 'rss'
require 'net/https'
require 'json'

CW_API_TOKEN = "API"
ROOM_ID = "ROOM_ID"

def post_msg_to_cw(data)
  uri = URI('https://api.chatwork.com/v1/rooms/' + ROOM_ID + '/messages')
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE

  header = { "X-ChatWorkToken" => CW_API_TOKEN }
  body = "body=" + URI.encode(data)

  res = http.post(uri, body, header)
  puts JSON.parse(res.body)
end

post_msg_to_cw(ARGV[0])
```

あとはこのコードをcronでうまいこと設定すれば終わりです。

# MacでCron

本来なら常に動いているサーバーのcronを使いたいところですが、今回はめんどいのでローカルのmacに入れときます。

```rb
*/10 11 19 * * ruby /Users/USERNAME/DIRECTORY/filename.rb "経費精算のお仕事をしましょう"
```

# References

参考というか、ほぼそのままやったのですが、以下を見てやってみました。

- http://dev.classmethod.jp/client-side/language-client-side/use-chatwork-api/
- http://togattti.hateblo.jp/entry/2014/03/26/231520
- http://blog.hello-world.jp.net/mac-2/2023/
mysqlの空間インデックス(spatial index)で思うような結果が出なかったら読んで下さい。

#結論から書きます。
例えばある緯度経度が含まれる市町村の名前を探すアプリケーションをmysqlで実現したい場合は、、、
１．検索にはmysql5.6を使って下さい。
２．mysql5.6以前のバージョンでデータを入力しても、それはそのまま使えます。
という事を言いたいだけです。検証に結構時間がかかったので、共有しておきます。

#問題点
緯度経度情報から市町村を取得する必要があって、色々調べていたら、次のページをみつけました。
http://gihyo.jp/dev/feature/01/location-based-services/0005?page=2

mysqlで緯度経度をポリゴンの形式で保持することが出来ます。
また、任意の緯度経度を含んだデータを引っ張ってくる事も可能です。
例えばこんなテーブルを作成して、、、

```
CREATE TABLE geo (
	name VARCHAR(255) NOT NULL,
	geo GEOMETRY NOT NULL,
	PRIMARY KEY (geo_id),
	SPATIAL KEY (geo)
)ENGINE=MyISAM;
```

こんな感じで登録して、、、

```
INSERT INTO geo (name,geo) values ('ハートンホテル', polygonFromText('POLYGON((135.760497 35.012033,135.760497 35.011655, 135.760970 35.011655, 135.760970 35.012033,135.760497 35.012033))'));
```

こんな風に検索しようという話です。

```
mysql> select count(*) from geo where MBRIntersects(GeomFromText('POINT(140.174560546875 35.64306822520527)'), geo);
```

上記の参考資料くらいのデータ量だと特に問題もなくハッピーなのですが、例えば日本の市町村データをテーブルに入れたりすると複数のエリアが検索されてしまいます（情報の集め方は後述します）。

```
mysql> select count(*) from geo where MBRIntersects(GeomFromText('POINT(140.174560546875 35.64306822520527)'), geo);
+----------+
| count(*) |
+----------+
|   3      |
+----------+
```

、、、こんな感じ。google mapに領域を書いて確認してみましたが、複数のエリアが被っているという事はありませんでした。

色々ぐぐってみると、mysql5.6より前は、polygonの検索にpointは対応してないよ、、、的な事が出てきたので、強引に次のようにしてみました。

```
mysql> select count(*) geo city where MBRIntersects(GeomFromText('LINESTRING(140.174560546875 35.64306822520527, 140.174560546876 35.64306822520528)'), geo);
+----------+
| count(*) |
+----------+
|   3      |
+----------+
```

が、結果は同じです。

#対策
そこからまたひたすらググってみて、次の記事を見つけました。
http://www.percona.com/blog/2013/10/21/using-the-new-spatial-functions-in-mysql-5-6-for-geo-enabled-applications/

で、ここで結論なのですが、mysql5.6にしないと、思ったような結果は出ないみたいです。
Mysql5.6だと次のように検索出来ます。

```
SELECT count(*) FROM geo WHERE st_contains(geo, point(140.174560546875,35.64306822520527));
+----------+
| count(*) |
+----------+
|   1      |
+----------+
```

なお、データ自体はMysql5.5で入力したものです。単純に計算アルゴリズムだけの問題のようです。

#追記
都道府県の領域情報の収集は、このデータは次の記事を参考にさせて頂きました。
http://qiita.com/hamichamp/items/ac9e80f1078febb9f1b9

参考資料ではMongoDBを使っています。これも試しましたが、Mysqlのような問題はありませんでした。
ちなみにdebian/ubuntuユーザーの方向けですが、apt-getを単純にしても、（現時点では）mysql5.6はインストールできません。
ただ、oracleのサイトにapt-getでmysql5.6をインストールできるようにするdebファイルがありますので、それをダウンロードすると幸せになるかもしれません。
古いThinkpadにLinuxを入れてSelenium用にする

<font color=deeppink>**Seleniumを動かすPCが欲しい！(｡･ω･｡)** :two_hearts: </font> 
が、高いPCは買えないので、古いThinkPadを改造して頑張ってみる。
http://support.lenovo.com/jp/ja/documents/pd020702
ハードのほうはSSD交換とメモリ増設を実施し、今回かかった価格は、だいたい
**Thinkpad:5000円
SSD:6000円
メモリ:2500円**
でした。その他諸々合わせても**15000円弱**。新品より全然お安いハズ。
そのPCに色々いれていく。


##isoをダウンロードしてUSBに入れる
この作業はWindows環境でしてます。CD入れるトコは無いのでUSBで取り込む。

1. まずは下記からbean14041-140826.isoをダウンロード。<br />
http://sourceforge.jp/projects/linuxbean/
1. それでそのファイルをuNetbootinでUSBに入れる。ディストリビューションはUbuntu選択でいけた。<br />
http://unetbootin.sourceforge.net/

#インストールする

1. USBをさす前にUSBから起動させるようにBIOSで設定してから！(大昔、ここでつまづいた。)USBをThinkPadにさしてインストール！
2. 画面が出てきたら「Normal Live boot」を選択。画面にあるインストールのアイコンをクリックしたインストール！<br />
[参考にしたサイト]<br />
http://mogi2fruits.net/blog/os-software/linux/linuxbean/2181/#LiveCDUSB
3. インストールできたらBIOS設定でHDD起動に切り替えて起動。

#Seleniumを使えるようにする

1. インターネット接続設定をしたらjavaとFirefoxは「linuxBean設定ウィザード」でインストール。あとはSeleniumServerをダウンロード。<br />
seleniumはselenium-server-standalone-2.44.0.jarです。<br />
sshを入れたかったら`sudo apt-get update`からの`sudo apt-get install ssh`でOK。<br />
[参考にしたサイト]<br />
http://www.seleniumhq.org/download/
2. ターミナルで`java -jar selenium-server-standalone-2.44.0.jar`
を実行してみて無事たちあがったらOK。こんなカンジの状態になります。

> 01:20:52.098 INFO - Launching a standalone server
> 01:20:52.488 INFO - Java: Oracle Corporation 23.5-b02
> 01:20:52.488 INFO - OS: Windows 7 6.1 x86
> ・・・・・・
> 01:20:53.158 INFO - Started HttpContext[/wd,/wd]
> 01:20:53.205 INFO - Started SocketListener on 0.0.0.0:4444
> 01:20:53.205 INFO - Started org.openqa.jetty.jetty.Server
.DS_StoreをBacklogなどのファイル共有フォルダに生成しない方法

Mac OS X を利用してファイル共有フォルダを操作すると、
他環境などでは.DS_Storeファイルが生成されてとても厄介です。
[Backlogのファイル共有](http://www.backlog.jp/help/usersguide/file/userguide234.html)に至っては、._.DS_Storeなんて、一見可愛いファイルまでも生成されてしまい、
![Backlogの恥ずかしい状態](https://qiita-image-store.s3.amazonaws.com/0/37964/72896987-bf4d-0166-bd4c-5b4482d5ce6f.png)
操作する毎にプロジェクトホームにも表示されてしまうので、とても恥ずかしいです。

## 停止
「ターミナル」から以下のコマンドを実行。

```lang:コマンド
defaults write com.apple.desktopservices DSDontWriteNetworkStores true
```

その後、再起動。

## 再開
「ターミナル」から以下のコマンドを実行。

```lang:コマンド
defaults write com.apple.desktopservices DSDontWriteNetworkStores false
```

その後、再起動。
【Rails】ValidationでBoolean型を入力必須にしたいとき

RailsでBoolean型をRadioButtonで実装していて入力必須にしたいときにいつものように```presence: true```やったらだめだったのでメモです。

## ダメなやつ

```rb
 validates :XXXXX, presence: true
```
 いつもの感じでこのようにやるとfalseにした場合には何も入力されていないと認識されてしまい、エラーにひっかかってしまいます。

## 解決策

```rb
validates :XXXXX, inclusion:{in: [true, false]}
```

```inclusion``` でtrueかfalseが含まれているかを確認しましょう。
これでうまくいきました。

## 参考

Ruby on Rails バリデーションでbooleanを必須にしたい - ayaketanのプログラミング勉強日記
http://ayaketan.hatenablog.com/entry/2012/12/22/203728
pepperめも_06:ペッパーのタブレットの解像度とかまとめ

#ペッパーのタブレットの解像度とかまとめ
ペッパーのタブレットの解像度とかをまとめました！

※旧型ペッパーの情報です！

※随時追記していきます

#各種情報
確認くんみたいなのを作ってペッパーで表示してみました！

http://tonosamart.com/pepper/ua.php

```php:sample.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="target-densitydpi=device-dpi, width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        body {
            -webkit-transform-style: preserve-3d;
            font-size: 40px;
        }
    </style>
</head>
<body>
    <a href="">screen</a><br>
    <script>
    for(var propertyName in screen){
        var propertyValue = screen[propertyName];
        document.write(propertyName + ":" + propertyValue + "<br>");
    }
    </script>
    window<br>
    <script>
    for(var propertyName in window){
        var propertyValue = window[propertyName];
        document.write(propertyName + ":" + propertyValue + "<br>");
    }
    </script>
    <br>
    <?php echo "REMOTE_ADDR:" . $_SERVER["REMOTE_ADDR"]; ?><br>
    <?php echo "HTTP_ACCEPT_LANGUAGE:" . $_SERVER['HTTP_ACCEPT_LANGUAGE']; ?><br>
    <?php echo "HTTP_USER_AGENT:" . $_SERVER[ "HTTP_USER_AGENT"]; ?><br>
</body>
</html>
```

viewport指定は、こんな感じにしました。

```php:sample.html
<meta name="viewport" content="target-densitydpi=device-dpi, width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />
```

target-densitydpi=device-dpi としたので、
表示する解像度＝デバイスの解像度になる作戦です。

## デバイスの解像度
いきなり衝撃なのですが、1280x800じゃなかった・・・。あれれ？

![名称未設定-1.png](https://qiita-image-store.s3.amazonaws.com/0/40994/6b1fb006-89d0-a7a9-9c06-9ebedfac43bb.png)

実行結果を見ると、

```
width:1707
height:1019
```

となっています。

Pepperチュートリアル (5)：タブレットを使う
http://qiita.com/Atelier-Akihabara/items/87def938b6553ee9c1e9

には、解像度 1280 x 800って書いてあったので謎です。

## 画面の解像度
こっちは、windowの値です。

![名称未設定-1.png](https://qiita-image-store.s3.amazonaws.com/0/40994/7fc68f91-898c-4f89-88b7-a865554a67c2.png)

1280x801になってます。800じゃないの？

![名称未設定-2.png](https://qiita-image-store.s3.amazonaws.com/0/40994/0c1ea0f2-b2fa-6b21-651e-38ab65cfb85c.png)

これが0.75なので、

```
1707x0.75 = 1280.75
1019x0.75 = 764.25
```

なんか計算あわないなあ・・・
よくわかんないので、だれかおしえてください！

## おまけ：USER_AGENTとか
ペッパーのUSER_AGENTはこんな感じでした！(2014年11月25日現在)

![名称未設定-1.png](https://qiita-image-store.s3.amazonaws.com/0/40994/097126f8-627d-24be-fdda-65cd2171b3dc.png)

#おしまい
以上、ペッパーのタブレットの解像度とかまとめでした！
grape による Web API化 でハマった小さな点 --Rails と iOS 連携の下準備--

Rails で作成した Web アプリと iPhone アプリとの連携を行おうとあれこれ試す中で、grape を用いて少しハマった。そのことについて書いていこうと思う。

<h2>Rails と iOS の連携について</h2>
Rails と iOS で連携するには、基本的には Rails 側のデータを API化して、HTTPリクエストで扱える状態にした上で、iOS側でも適切なライブラリを導入し、それらのデータを扱えるようにすればいいだけの話である。

そして、今回はその第一段階として、すでに作成済みの Web アプリにおいて、データの API化 を grape という gem を用いて試してみた。ところが、かなり小さいところではまってしまったので、これから grape を使う人のために記録しておこうと思う。（本当に小さな点なので、この記事が読まれる頃には改善されている可能性がある。）

<h2>grape の使い方について</h2>
grape 自体の使い方については、<a href="https://github.com/intridea/grape">公式リファレンス</a>か、あるいは、<a href="http://qiita.com/fakestarbaby/items/fa03cf333744b7c70e72">こちらの記事</a>や<a href="http://makotton.com/2014/07/11/310">こちらの記事</a>に詳しい。ので、実際の使い方はこれらの記事を参考にしてほしい。しかし、この通りに作成し、api 以下にアクセスしたところ、` uninitialized constant API (NameError)`というエラーを受け取ってしまった。どうやらルーティングがまずいらしい。

ということで調べたところ、<a href="http://stackoverflow.com/questions/24833131/rails-4-mounting-a-route-returns-errors">このような記事</a>を見つけた。この記事によれば、grape の公式ドキュメントにあるように、Rails は api ディレクトリの中のモジュール名のついたディレクトリ配下のファイルを探すらしく、そのため、ディレクトリ構造としては、`app/api/api.rb`ではなく、`app/api/api/api.rb`が正しい、ということらしい。確かにこうすると問題は解決した。

ただ、まだ理解が甘いところがある上、こうして書いてみても、自分で「本当か？」と思ってしまう説明ではあるので、また改めて理解が進めば加筆・修正していきたいと思う。ご指摘などいただければ幸いです。
GCM(Google Cloud Messaging)とChrome extensionでデスクトップへプッシュする仕組みを作る

# はじめに
GCM(Google Cloud Messaging)とChrome extensionを使って簡単なデスクトップ通知をプッシュする仕組みを作ってみる

## 下準備
* [Google API Console](https://console.developers.google.com/project)にGoogleアカウントでログイン
* 新しいプロジェクトを作る
* 該当プロジェクトのトップページに記載されているプロジェクト番号をどこかに控えておく
* APIと認証→APIをたどり、**Google Cloud Messaging for Android**と**Google Cloud Messaging for Chrome**と有効化（一応、どっちも有効化しました）
* APIと認証→認証情報でサーバー アプリケーションのキー欄を確認
* プッシュ通知を行うサーバのIPなどで制限をかけるなどの確認をして、最後にAPIキーを控えておく

## Chrome拡張の準備

ブラウザの右上にアイコンを出して簡単なUIを出したりということもできるけど、ここでは単純にChromeの持つデスクトップ通知機能を使ってピョコッと右下に出して終わりにしておく
jqueryはあれば何かと便利なのでDLして、minifyしたやつをjquery.min.jsという名前でこれらのファイルと同じディレクトリに置いてください
icon.pngは128×128の適当なpngファイルを用意しといてくださいまし

```json:manifest.json
{
	"manifest_version": 2,
	"name": "デスクトップ通知",
	"version": "0.1",
	"description": "デスクトップ通知",
	"icons": {
		"16": "icon.png",
		"48": "icon.png",
		"128": "icon.png"
	},

	"background" : {
		"scripts": [
			"jquery.min.js",
			"background.js"
		],
		"persistent": true
	},

	"permissions": [
		"gcm", "notifications"
	]
}
```

```javascript:background.js
var onstartup = function(){
	//	CGM登録
	if(!window.localStorage.getItem('registrationId')){
		chrome.gcm.register(['プロジェクト番号'], function(registrationId){
			$.ajax({
				type: 'POST',
				url : 'サーバアプリのURL',
				data: {
					registrationId: registrationId
				}
			}).done(function(data){
				window.localStorage.setItem('registrationId', registrationId);
			}).fail(function(xhr){
				alert('登録に失敗しました');
			}).always(function(){
			});
		});
	}
}

chrome.runtime.onInstalled.addListener(onstartup);
chrome.runtime.onStartup.addListener(onstartup);

chrome.gcm.onMessage.addListener(function(message){
	chrome.notifications.create('', {
		title: message.data.title,
		message: message.data.message,
		type:'basic',
		iconUrl: 'icon.png'
	}, function(id){
	});
});
```

## サーバアプリの準備
上のextensionの例だと、自分のregistrationIdをサーバに送信します
サーバは通知先を指定するのにこのregistrationIdというものが必須なので、サーバ側のアプリはこのIDをDBあたりに保存しておいてください
この辺の実装は色々あるので割愛

サーバアプリからGCMサーバへプッシュ送信を依頼するには、node.jsの場合

```js:gcm.js
var request = require('request');
request.post({
	url     : 'https://android.googleapis.com/gcm/send',
	headers : {
		Authorization:'key=控えておいたAPIキー'
	},
	json    : true,
	body    : {
		data: {
			title: 'はろー',
			message: 'わーるど'
		},
		registration_ids: ['送信先', 'registration_Idの', 'リスト']
	},
	encoding: 'utf-8'
}, function(err, response, body){
	console.log(body);
});
```
みたいな形で、https://android.googleapis.com/gcm/send にAPIキーをしのばせたheaderをしこんだ上で、content-type: application/jsonと宣言して、JSONデータをリクエストボディにそのまま突っ込んでPOSTする
同じ動作するならサーバ側の言語は問わないし、ライブラリがあるならおそらくそれを使ったほうが簡単

## デバッグ
ここの例のextensionはlocalStorageにregistrationIdを保存しておいて何回もregister()を呼び出すのを抑制しているものの、registrationIdはextensionとGoogleアカウントの組み合わせでほぼ固定っぽいので、サーバ側のロジックのデバッグにテストの配信先が必要な場合はextension側で一度chrome.gcm.register()のコールバック関数で取れるregistrationIdをどこか（console.logとか）に出力して控えておいて、サーバ側からそのregistrationIdだけに向けてPOSTする部分だけ作ってテストしてた

## 最後
ここのコードについては、実際に作ったものから業務に関係しそうなところを削除したものなので、完全な動作については無保証です
割とよく使われていたっぽいのに、deprecatedになっているAPIなどもあるので(前はHTMLからNotificationのコンテンツを作れるとかもできたらしい）、本家のGoogleのドキュメントを参考にしながらやると捗ります
[AWS][EIP]汚れたIPじゃないかspamhausでチェックする



# 汚れたEIP？？

別のアカウントが使っていた時に
大量にメールをスパム送信していてspamhausに登録されちゃっているEIP


# spamhaus？？

Spamhaus.orgとは、スパムに荷担しているドメインやIPアドレスをリアルタイムに作成したリストを公開している組織。
（Spamhausに登録されているリストは、スパムメール対策以外にも利用されていることもあるので注意）

日本語のFAQもある
http://www.spamhaus.org/faq/pblfaqjp.html


# EIP取得〜汚れていないことを確認

## EIP取得

aws cli で取得

```
aws ec2 allocate-address --domain vpc
```

```
{
    "PublicIp": "xx.xx.xx.xxx",
    "Domain": "vpc",
    "AllocationId": "eipalloc-xxxxxxxx"
}
```


## spamhausに登録されていないか確認


![0001.png](https://qiita-image-store.s3.amazonaws.com/0/17518/5b9a380c-568d-f9a1-847b-0d3d072ee91b.png "0001.png")


![0002.png](https://qiita-image-store.s3.amazonaws.com/0/17518/31e2e7f0-9c3f-e740-874c-400075d10af8.png "0002.png")


`Listed` になったIPは汚れちまったIPなので捨てる
か
spamhausに連絡してリストから外してもらう
（まあ捨てるほうが早い）

![0003.png](https://qiita-image-store.s3.amazonaws.com/0/17518/a3125ccc-3e9a-5741-5cc5-f3c11ff79f9a.png "0003.png")
Windows Azureの初期起動時に英語→日本語にする

# これは何？
Windows Azureでインスタンス起動時に英語版になっている場合がある。
それに日本語版を追加する手順をメモする。

# 手順
1.　[control panel] -> [language] を開く
2.　[Add a language] で「日本語」を追加する
3.　追加されたあと、Optionを選択し、[download and Install language pack]をクリックしてLanguage Packをダウンロードする。（20分程度かかる？）
4.　ログオフ　→　ログイン　で日本語化されている。

参考：http://blogs.msdn.com/b/daisukei/archive/2013/08/16/windows-azure-windows-server-2012-ok.aspx
Xcode6で、StoryBoardなしのEmptyApplicationテンプレートを使用する方法

# Xcode6で、StoryBoardなしで使用する設定

## AppDelegate.mに書きを記述

```ruby

#import "ViewController.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    ViewController *viewController = [[ViewController alloc] init];
    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

```
AWS LambdaをRubyから使ってみる

AWS LambdaはS3やKinesis、DynamoDBのイベントをトリガーにJavaScript/Node.jsで書かれたコードスニペットを実行するというサービスです。
イベントの実行元として上記以外にAPIからの直接実行も可能となっているので今回はAWS SDK for Rubyを利用してこれを試してみます。
なお、AWS Lambdaをサポートしているのはv2だけとなります。

実際のところ、Rubyアプリケーションから実行することはないと思います。
なぜならRubyのアプリを動かすということは恐らくEC2なり何らかのサーバ上で実行してると思われるからです。
でも、例えばクライアントサイドとしてRubyを使うツールを用意して少しだけサーバサイドで処理したいっていうときにEC2とか立てる必要がないのは嬉しいかも知れません。
そんなシチュエーションあるかはわかりませんが。
というわけで早速やってみます。

今回はシンプルに登録済みのLambda functionをRubyのコードから実行するだけにしますが、Lambda functionの作成から実行するコードのアップロードもRubyで実行することが可能です。

とりあえずGemfileはこんな感じにします。

```text:Gemfile
source "https://rubygems.org"

gem 'aws-sdk', '2.0.10.pre'

```

まず、Lambda functionとして登録するコードを以下のように用意します。今回はシンプルに実行時に渡されるパラメータの値を読み取ってログ出力するだけです。

```js:sample.js
exports.handler = function(event, context) {
    console.log('value1 = ' + event.key1);
    context.done(null, 'Invoke from Ruby');
};

```

新たにLambda functionを作成してこのコードを登録しておいてください。
今回はとりあえずのお試しなのでその他のパラメータはデフォルトで構いません。また、今回はSDKからの実行ですのでEvent Sourceの指定は行いません。
名前は適当につけます。例ではinvoke-from-rubyという名前にしました。

さて、次に作成したLambda functionを起動するRuby側のコードを用意します。

```rb:sample.rb
require 'aws-sdk'

Aws.config[:region] = "us-east-1"
lambda = Aws::Lambda::Client.new

begin
	param = { key1: "from ruby"}.to_json #=>functionに渡すパラメータをJSON形式で作成
	
	resp = lambda.invoke_async(function_name: "invoke-from-ruby", invoke_args: param)

 	if resp[:status] == 202
  		puts "success"
  	end
rescue Aws::Lambda::Errors::ServiceError => e
  	p e.message
end
```

これだけです。
functionに渡すパラメータはJSON形式で用意します。ここで指定したJSON形式のパラメータがfunction側ではeventとしてJavaScriptのmoduleに渡されます。
先ほど用意したJavaScriptのコードではkey1というキーの値を読み取っています。

レスポンスのステータスが202であれば成功しています。ただし、実際には非同期で実行されます。
また、指定したfunctionが存在しない場合やその他のエラーが発生した場合は例外が発生しますので適切に処理してください。

Lambdaでconsole.logした場合の出力はCloudWatch Logsに出力されますのでこちらを確認してみます。
マネージメントコンソール上でCloudWatchからのLogsにfunction名と同じLog Groupが存在しているので実行したfunction名のものを表示してみてください。

![Screen Shot 2014-11-25 at 3.13.08 PM.png](https://qiita-image-store.s3.amazonaws.com/0/30135/252f9518-c24b-61d1-e9a7-dec4bf821d07.png)

なお、このプログラムを実行するユーザにはlambda:InvokeAsyncの権限が必要となりますので、このプログラムを実行するIAMのUserもしくはRoleにPolicyで許可しておいてください。

こんな感じでAWS LambdaとAWS SDK for Rubyを使ってEC2を使わずにサーバサイドの処理を実行することが可能になります。
たった10数行書くだけでEC2立ててゴニョゴニョしたりしなくていいのは非常に楽ですね。

最後に、大人のたしなみとしてお約束の文章を書いておきます。

**免責
こちらは個人の意見で、所属する企業や団体は関係ありません。**
【Xcode】スワイプページの上部がずれる場合は「Under Top Bar」のチェックを外す


## 状況
RootViewController->DataViewControllerのスワイプページで、上にナビゲーションを付けた。
Navigation
　|- RootView
　　|- DataView
    

![b5ed5975efa0dfaf3429fb63ae5bf450.png](https://qiita-image-store.s3.amazonaws.com/0/28556/35b61b1a-64a5-f30e-07a6-ace9e95709e4.png "b5ed5975efa0dfaf3429fb63ae5bf450.png")

RootViewが、スライダーの"台"的部分、DataViewが"個々のスライド"のコントローラ。両者がModelControllerを介してつながっている。更にNavigationControllerがRootViewControllerとつながっている。
Navigationは上部にページタイトル「スライダー」を表示させているのみ。

これはXcodeで新規プロジェクト作成時に「Page Based Application」を選択して作られるやつのほぼそのまま。
![ダイアログ](http://i.gyazo.com/5b8072cbd7470fe75fb7022be4cba5fd.png)

## 現象
シミュレータ実行すると、初期表示画面をタップしたらナビゲーションの幅分画面が上にずれる。
![ずれる](http://i.gyazo.com/7240c62e153d2d4974576166334586e7.gif)
↑スライドした後も青枠のヘッダーを表示させたいのだが、初回のタップで消えてしまう。

## 解決策
Xcode上で、RootViewController - AttributeInspector - ViewController - Extend Edgesで「Under Top Bar」のチェックを外す。
![889d2249bf35977ff85f53b40c684904.png](https://qiita-image-store.s3.amazonaws.com/0/28556/f127b1ca-e076-7a63-7604-e66f73a860ce.png "889d2249bf35977ff85f53b40c684904.png")

青枠が表示され続けるようになりました。
![ずれない](http://i.gyazo.com/1eac28c3bad1a573532f6cbc04d9b289.gif)

## ソース
こちらに置きました。
https://github.com/hanoopy/SliderSample

## その他
* Xcodeでやらなくてもソースでできると思う。
* 画像は写真ACから使わせてもらいました。
http://www.photo-ac.com/
WebStorm から見ているファイルを Vim で起動する

## なぜ WebStorm から Vim を起動する必要があるのか？

普段は WebStorm 上のキーバインドは ideaVIM を使っているんですが、やっぱりまだまだ本物の Vim にはかないません。
そこでガッツリとファイルの修正をする場合は Vim を起動するのもひとつの手です。

また、CoffeeScript などで定義元に移動みたいなことや、リファクタリングはやはり圧倒的に WebStorm が使いやすいため、WebStorm で移動してから、 Vim で開くなどでもぜんぜん使いやすいのではないでしょうか。

## External Tools の設定をする

まずは外部ツールと連携します。
以下のリンクのとおり、External Tools から設定します。

### Program:
/Applications/MacVim.app

### Parameters:
\$FilePath$

### Working directory:
/Applications/MacVim.app

[Running External Tools in PhpStorm](http://confluence.jetbrains.com/display/PhpStorm/Running+External+Tools+in+PhpStorm)

## Keymap を設定する

あとは、ショートカットを設定するだけ。

ぼくは *Shift + Cmd + v* にしました。

## 余談：WebStorm にもvimrc的なものを読み込む仕組みがある

*.ideavimrc* というファイルをHOMEディレクトリに置いておくと、読み込んでくれます。
ただ、NeoBundle などで読み込んだプラグインなどは使えないようです。

なので、 *.ideavimrc* には必要で且つ動きそうなものだけを書いています。

参考までに、ぼくのをば。

[.ideavimrc](https://github.com/hisasann/dotfile/blob/master/.ideavimrc)
Pound設定メモ書き

これまでELBを使ってサービスを展開していましたが、比較的安価に柔軟なスケーリングができる反面、できないことも多いため、EC2+Poundで置き換えられないかと思い研究中です。
ELBの中身ってひょっとしてPoundなんじゃね？と思うほど仕様がよく似ていますので、移行自体は非常に簡単です。
また、Poundだけであれば非常に消費リソースも少ないので、そこそこのトラフィックもさばけそうです。

で、以下はPoundの設定ファイルとちょっとした注意点です。
インストールは普通にyumでできますので、省略します。

```/etc/pound.cfg
User "pound"
Group "pound"
Control "/var/lib/pound/pound.cfg"

LogLevel 3

Alive 30

ListenHTTP
	Address 0.0.0.0
	Port 80
	RewriteLocation 0
        Service
                HeadRequire "Host: XXXXX.example.co.jp"
                BackEnd
                        Address AAA.AAA.AAA.AAA
                        Port    80
                End
                BackEnd
                        Address BBB.BBB.BBB.BBB
                        Port    80
                End
	End
End

ListenHTTPS
	Address 0.0.0.0
	Port    443
	Cert    "/etc/sslkeys/example.co.jp.pem"
	xHTTP	0
	RewriteLocation 0
	AddHeader "X-Forwarded-Proto: https"
	AddHeader "X-Forwarded-By: SSL"
	AddHeader "X-Forwarded-Host: SSL"
        AddHeader "X-Forwarded-Port: 443"
	HeadRemove "X-Forwarded-Proto"
	HeadRemove "X-Forwarded-By"
	HeadRemove "X-Forwarded-Host"
	HeadRemove "X-Forwarded-Port"
        Service
                HeadRequire "Host: XXXXX.example.co.jp"
                BackEnd
                        Address AAA.AAA.AAA.AAA
                        Port    80
                End
                BackEnd
                        Address BBB.BBB.BBB.BBB
                        Port    80
                End
        End
End
```

涙がでるほど簡単ですね。
幼稚園児でも一見して理解できるほど単純な構造です。
そして一見して分かる通り、SSL周りに関してはELBと全く同じ仕様をとっています。
80ポートアクセス時は通常通りの割り振り。
443ポートアクセス時は、ヘッダ類を付与した上でバックエンドに80ポート経由で割り振り。
なお、今回はまだ設定していませんが、<b>ロードバランサレベルでの仮想ホストの設定も可能ですし、仮想ホストごとにバックエンドを振り分けることも可能です</b>。
有能ですね、Poundさん。
***
ちなみに、うちの会社とサービス基準ですが、留意点は以下の3つです。

#### 1. アクセス制御方法の取り扱い方法を決めておく

　SecurityGroupは引き続きELBと同じものをEC2単位で使用可能ですが、それに加えて「iptables」「Poundのアクセス制御」の2つが使用可能になります。
　iptablesは機能的にSecurityGroupと近いネットワーク層のセキュリティシステムで、Poundのアクセス制御はapacheのAllowDenyと近いアプリケーション層のセキュリティシステムです。
　パターンに応じた柔軟なアクセス制御が実現できるようになるので、運用しているサービスに対応したアクセス制御方法を取り決めておく必要があります。

#### 2. ログの出力先に注意する

　もしyumで入れたり特に設定せずmakeした場合、ログの出力先は<b>/var/log/messages</b>になってしまいます。後から変更するには、残念ながらsyslogを調整するしかないようです。
　また、LogLevelとrotationも必要に応じて調整する必要があります。

#### 3. 転送時の挙動を設定する

　さり気なく先述のログサンプル内に書いてあった以下の部分がこれに相当します。

> RewriteLocation 0

RewriteLocationの値と挙動は以下の通りです。


>0 : RewriteLocationを一切無効にする
>1 : Poundの設定通りに書き換える（デフォルト）
>2 : バックエンドの設定通りに書き換えて、もしバックエンドから指定されていなければPoundの設定通りに書き換える

例えばバックエンド側で「このURLにリダイレクト！」と命令しても、デフォルトのままではPoundの設定を優先してしまうため、うまくリダイレクトが働かないことがあります。
　うちのサービスでもApacheやCakePHPがバックエンド側からHTTP→HTTPSのリダイレクトをかけていましたが、何度やっても無限ループになってしまっていました。ドツボにはまっていたのでmanを確認していたところRewriteLocationに行き当たり、解決した次第です。
***
以上です。

今後はモニタリングとスケーリングの自動化について研究していきます。
pepperめも_05:道路交通法違反になるって噂を聞いたから確認してみた

#道路交通法違反になるの？
ペッパーが道路交通法違反になるって噂を聞いたから確認してみました。
とりあえず、個人的に動かしてみたり、会社から家までとかを、移動するときに
動かせるかを聞いてみました。

※随時追記していきます

#どこに確認すればいいのか
住んでいる地域の警視庁に質問したら教えてくれるとのことなので、
東京の警視庁に電話しました。

※ボイスレコーダーとか使ってないので、大体の内容のメモになります。
実際に動かす場合は、状況に応じた個別の確認をしてください。

#質問の内容
「ペッパーっていう、ロボットを買ったんですけど、道路交通法に違反しますか？」という
質問をしたところ、ていねいに教えてもらえました！

#使用目的や状況によって変わる

```
ペッパーをどういうふうに使うかなど、使用目的や状況によって変わる
```

##乗ったら無免許運転などになる
```
ペッパーってどれくらいの性能かわからないんだけど、
もし人が乗って移動したりするなら、無免許運転とかそういうのになる。
```

乗らないから大丈夫ですと伝えました。
（なので、以下は人が乗らない前提の話になります）

##人集めやイベントに使うには許可がいる

```
人集めやイベントをするには、道路などの使用許可がいります。
```

とりあえず、イベントとかそういうのはやらないと伝えました。
（なので、以下は個人で使うのが前提の話になります）

##ペッパーくんはラジコンと同じ（遊具）

```
どういう操作かしらないけど、ラジコンと同じ遊具扱いになります。
```

と教えてもらいました。なるほど。わかりやすい。
自動操縦かどうかとかは、あんまり関係ないみたいでした。

そのばあい、以下の法律に違反する可能性があるとのことでした。

```
道路交通法　７６条４項第３項
４項　何人も、次の各号に掲げる行為は、してはならない。
三　交通のひんぱんな道路において、球戯をし、ローラー・スケートをし、又はこれらに類する行為をすること。
```

まあ、そうですよね！逆に言うと、交通ルールを守ってれば良さそうな気もしました。
この場合はあれですね、道路交通法７６条４項第３項に該当すると思いますね。みたいな感じにスラっと教えてもらったので、ビックリしました。

#注意事項

```
そもそも、ペッパーは屋外で使えない
```

って、ソフトバンクの人が言っていました。

#おしまい
以上、ペッパーくんが道路交通法違反になるか確認した結果でした！

なんかちょっとした移動とかで叱られると嫌なので、確認してみました。
ペッパーが最初に入ってた箱に入れて持ち運ぶのが無難みたいです。

警視庁の方が親切で、「たとえば、お掃除ロボットのルンバを公道で走らせた場合」とか、
「自動で動くっていうのは、ミニ四駆とかと同じですね。」など、
分かりやすく教えてもらえました！

迷惑がかからないように持ち運びたいです！
PlantUML を vim から使う


[plantUML](http://plantuml.sourceforge.net/) という UML図をテキストで記述できる、Java で書かれた便利ツールがあります。
これを vim から便利に使う手順です。

## 導入方法

### Plugin

https://github.com/aklt/plantuml-syntax

```.vimrc
NeoBundle "aklt/plantuml-syntax"

```

で `:NeoBundleInstall` します。

ファイル拡張子を認識し、シンタックスハイライトをしてくれるほか、make コマンドで実行等できます。

### make コマンド対応

ダウンロードしてきた `plantuml.jar` を、`~/lib/java/plantuml.jar` に置く。

以下の様なシェルスクリプトを `plantuml` という名前でパスが通っているところに置き、実行権限付けておく。

```plantuml
#!/bin/bash
java -jar $HOME/lib/java/plantuml.jar -tpng $@
```

### 実行

vim でファイルを開いて `:make` すると、
![スクリーンショット 2014-11-25 13.05.18.png](https://qiita-image-store.s3.amazonaws.com/0/4497/cb150c0d-3cbf-88e6-d85c-a7412ce85d75.png "スクリーンショット 2014-11-25 13.05.18.png")


png形式でUML図を吐き出してくれます。

※ コマンドラインオプションの `-tpng` を変更すると他の拡張子（例えばsvgだと `-tsvg`）で書き出す事もできます。

![スクリーンショット 2014-11-25 13.04.45.png](https://qiita-image-store.s3.amazonaws.com/0/4497/bbee6105-f182-e1e6-69b6-cd4da98233f2.png "スクリーンショット 2014-11-25 13.04.45.png")


---

http://plantuml.sourceforge.net/running.html を見ると、様々なツール、エディタと連携するプラグイン環境が整ってるようなので、皆さんお使いの環境に合わせて使われると良いのではないでしょうか。
Java SE 8のOracleの資格試験（beta版）を受けたのでレポ

Oracleが開いている Java SE 8 Programmer I のbeta版を受けてきました。
合格すると Oracle Certified Associate, Java SE8 Programmer（日本でいうところの Silver 相当）の認定を得られます。
Exam Numberは「1Z1-808」でした。（現在は、「1Z1-808」の公式ページにはアクセスできないようです）

# beta版の試験とは？
試験の正式リリースの前に実施される試験です。誰でも受験できます。
beta版では通常の試験の数倍の量の問題を出題して、それらの問題の中から、正式リリース版の試験で出題する問題を採用するそうです。
beta版の試験の成績は、正式リリース版の試験問題として採用された問題でのみ採点するそうなので、難易度は正式リリース版の試験と同じです。
試験結果は、beta版がクローズされてから11週以内に通知される、とのことです。結構な時間がかかりますね。

beta版は受験期間が決まっており、2014/11/15（土）までしか受けられませんでした。
なので現在は受験できませんが、

* Java SE 8 Programmer IIもbeta版があるかもしれない
* 公式リリース版の試験とかなり内容がかぶっているはず

なので、レポをします。

受験費用は5000円程度で、通常の1/5ほどでした。

# どうすればbeta版を受験できるの？
twitterで@OracleCertが
<blockquote class="twitter-tweet" lang="ja"><p>Java SE 8 OCA certification is now available at a significant discount by taking the 1Z1-808 beta exam. <a href="http://t.co/xfaqKyk0rW">http://t.co/xfaqKyk0rW</a></p>&mdash; Oracle Certification (@OracleCert) <a href="https://twitter.com/OracleCert/status/517996251716259840">2014, 10月 3</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
という具合にbeta版試験のリリースを告知しているようです。（なぜか@javacertの方では告知がないようです）

もしくは
[OracleCertificationの公式ブログでも通知があったようです](https://blogs.oracle.com/certification/entry/1118_03)
RSSを購読しておけばbeta版のリリースに気が付けますね。

Java以外の試験もこれらの方法で告知しているようです。

受験申し込みは、正式リリース版の試験と全く同じでした。
Pearson VUEから申し込むことになります。
全国に各地に小規模なテストセンターが大量にあって、ほぼ毎日いつでも受験できるみたいです。
申し込んでから数日で受験できるスピード感が楽しかったです。

ちなみにbeta版は日本語の情報がほとんどありませんでした。

# 試験内容
[正式リリース版の試験のページ](http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=5001&get_params=p_exam_id:1Z0-808)そのまんまですが、Javaのかなり基礎です。

* Stringのオブジェクトはイミュータブル
* static変数の性質
* staticメソッドの性質
* メソッドの仮引数は値渡し/参照の値渡し
* castできる条件・できない条件

がわかっていれば問題の1/3は解けそうでした。
Java SE 8特有のものとしては、公式ページに載っている通りですが、

* ものすごく基本的なラムダ式
* java.timeパッケージのかなり基礎的な部分

が出ました。

beta版だからか、試験はすべて英語でした。
試験問題の大半は英語がほとんどわからなくても意味が分かりますし、それほど時間に追われることはないと思い込んでいたため、私はかなりのんびりと受けました。
しかし、まれに20行程度の試験問題も出てきたりして、時間配分をしくじったために、後半はほとんど問題を読まずに勘で解く羽目になりました。
日本語でも時間不足であせることがあると思いますので、受験前にサンプル問題だけでも見ておけばよいでしょう。


# 試験のコツについて
ある程度経験があれば難なく解ける問題が多いかと思います。
なので焦らないように心掛けることが大切です。
## 普段意識しないことが出題される
あるメソッドがどういうExceptionを投げるかといった、普段はIDEが教えてくれる知識を改めて問われるので、ドキドキするかと思います。
ド忘れした知識もあるでしょうから、そういう問題はさくっと直感で答えて次に進みましょう。問題番号をメモして、思い出したら後で戻ってくるといいでしょう。
## 焦ったら問題を捨てる
これまでの試験の例を見ても、65%くらいの得点率で合格できるようですので、長文の問題は捨てるのも手だと思います。
私は、そうすればよかったな、とあとになってから思いました。
## 時間配分を意識し続ける
特にbeta版の場合は問題数が膨大なので（150問くらいあった気がします）、1問にどれだけの時間を使えるかを計算しておいて、順調かどうかをこまめにチェックするといいと思いました。
私の場合は、少しのズレが積み重なって最後に焦ったので、ズレを早めに見つけることが大切だと思います。
まれに長文の問題もあるという心構えを持って時間配分に気を付けるといいでしょう。
beta版の試験時間は2時間以上が設定されており、まずまずの長丁場ですが、問題数からいってさほど余裕はありません。
インストールしたGemを一括削除する

あれやこれやと試してて気づいたら開発端末にいろんなgemがインストールされてるってことよくあるよね。
bundlerがどうとかrbenvがどうとか細かい話は抜きにして。

というわけで自分のブログも含めていろんなところで何回も書いてるけどローカルにインストールされたgemをまとめて削除（アンインストール）する方法。

```bash
gem uni $(gem li --no-versions) -aIx
```

これで全て綺麗に削除できるので、必要なものをbundlerなりで入れていけばいい。
Backlog プロフェッショナルをWindows Azure上にインストールする


# これは何？
* Backlogのプロフェッショナル版をWindows Azure上にインストールする際のメモ

# インストール対象
* スペック：Windows Azure上のA2（2コア、3.5GBメモリ：2014年11月25日現在）
* OS：OpenLogic 6.5

# 手順

※　基本的には、[Backlogプロフェッショナル インストールガイド](https://www.backlog.jp/package/doc/professional/install-guide/install-guide.html)に従う。

## Javaのインストール

* Java SE 7JDKをOracle社が配布するRPM形式でインストールする。

* Oracle社のJava SE 7の[ダウンロードページ](http://www.oracle.com/technetwork/java/javase/downloads/index.html)へアクセスしてRPM版をダウンロードする
* WinSCP等でサーバに転送し、下記コマンドでインストール

```bash
sudo rpm -ivh jdk-7u71-linux-x64.rpm
```

* もともとOpenJDKが入っているので、インストールしたJavaが実行時に指定されるように変更する。

```
alternatives --install /usr/bin/java java /usr/java/default/bin/java 1700XX
```

※　パラメータ1 : 登録するリンク　ex.) /usr/bin/java
※　パラメータ2 : 登録先する名前　ex.) java
※　パラメータ3 : 実際に実行するパス　ex.) /usr/java/default/bin/java, /usr/java/jdk1.7.0_21/bin/java
※　パラメータ4 : 優先度、XXにバージョン番号。JDK1.7.0_71なら　170071にする。　ex.) 17021

```alternatives --config java``` 現在のJavaが```/usr/java/default/bin/java```になっているかどうか確認する。（さっきインストールしたものかどうか）

```java --version``` でOracleのJavaになったかどうか確認する。

参考：[Java SE 7 (JDK 1.7.x) のインストール (CentOS 6.3 64bit)](http://ameblo.jp/kurabeat/entry-11516745503.html)

## MySQL のインストール
サポートしているDBが

* MySQL 5.1
* MySQL 5.6

です。

```sudo yum install mysql-server```でサクッとMySQL5.1が入るはず。

5.6をインストールする場合は、[CentOS 6.4 に MySQL 5.6 をサクッとインストールする](http://blog.manabusakai.com/2013/04/centos-mysql56-install/)が参考になる。

## MySQLへの時刻を日本にしておく
/etc/my.cnfのタイムゾーンをいじる。

```
[mysqld]
...（略）
default-time-zone='+9:00'
```

を追記して、サーバ再起動。

参考：http://uncletechjam.blogspot.jp/2013/10/mysql.html
参考：http://fukumura.org/410.html

## Javaのフォント設定
```
yum install ipa-pgothic-fonts
```

```
mkdir $JAVA_HOME/jre/lib/fonts/fallback
ln -s /usr/share/fonts/ipa-pgothic/ipagp.ttf $JAVA_HOME/jre/lib/fonts/fallback/
```

※　AzureのOpen Logicの場合は、$JAVA_HOMEにパスが設定されていないので
```/usr/java/default/jre/lib/fonts/fallback```こんな感じ

## 追加パッケージのインストール

### Gitインストール（V1.7であることに注意する）
```yum install git```

### bind-utilsのインストール
```yum install bind-utils```

### libpng, giflib, libjpeg のインストール
```yum install libpng giflib libjpeg```

## データベースドライバのダウンロード・インストール
* Java言語用 MySQLデータベースドライバを　http://dev.mysql.com/downloads/connector/j/ からダウンロード
* mysql-connector-java-XXX-bin.jar」を、Backlogパッケージをダウンロードしたディレクトリにコピー

```
tar zxfv mysql-connector-java-5.1.34.tar.gz
cp mysql-connector-java-5.1.34/mysql-connector-java-5.1.34-bin.jar /tmp/backlog-1.8.0/
```

* Perl用のMySQLデータベースドライバのアップデート
```
yum install perl-DBD-MySQL
```

## MySQLの初期設定

### Confの修正
my.cnfに下記に追加し、再起動
```
max_allowed_packet = 16M
```

### データベース作成

```
mysql -u root -p
mysql> GRANT ALL PRIVILEGES ON *.* TO 'backlog'@'localhost' IDENTIFIED BY 'backlog' WITH GRANT OPTION;
```

```
mysqladmin -u backlog -p create backlog
```

## RPMのインストール

```
sudo rpm -ivh \
  backlog-app-1.8.0-01.el6.noarch.rpm \
  backlog-www-1.8.0-01.el6.x86_64.rpm \
  backlog-mobile-1.8.0-01.el6.x86_64.rpm \
  backlog-git-1.8.0-01.el6.x86_64.rpm \
  backlog-api-1.8.0-01.el6.noarch.rpm
```

### 環境設定ツールに従って起動

```
/opt/backlog/bin/init.sh
```

終わり。
Fakerでダミーデータを生成する

Fakerというライブラリを利用してRubyでダミーデータを扱います。

Faker [https://github.com/stympy/faker](https://github.com/stympy/faker)

生成してくれるデータは名前、住所以外にもメールアドレスなど多岐に渡ります。
インストールはいつものようにgem install fakerしてください。

以下のようなサンプルを用意して実行してみます。

```ruby:sample.rb
#coding utf-8

require 'faker'
require 'Set'

puts Faker::Code.ean #=> EANコード
puts Faker::Name.name #=> 氏名
puts Faker::Lorem.sentence #=> loremな文章
```

今回は商品識別コードであるEANコード（日本のJANコードみたいなやつ）、氏名とLorem ipsum（一種のダミーテキスト）を出力してみます。
これを実行してみるとこんな感じになります。

```bash
$ ruby sample.rb 
8227509485998
Osvaldo Trantow
Nihil voluptatem voluptatem ut.
```

Fakerは便利なことに多言語対応していてロケールを切り替えれば各ロケール固有のフェイクデータを作成できます。
例えば日本にセットすれば日本名の姓名が生成されます。これは単にlib/localesにあるメッセージファイルに記載しているだけなのでここに追加すればバリエーションを増やすことも可能だと思われます。

```rb:lib/locales
Faker::Config.locale = :ja

puts Faker::Name.name #=> 日本語氏名
puts Faker::Address.name #=> 住所
```

生成できるデータの種類は多岐に渡り、インターネット関連だとメールアドレス、ドメイン、URLなどもあります。それ以外にも各種住所関連、クレジットカード番号とか電話番号が生成できたりします。
加えてそれぞれ結構細かい単位で生成することもできて痒いところに手が届く感じなので、テストコードなんかでダミーのパラメータを用意するときとか地味に面倒なのですごく役に立つかと。

注:この記事は[ブログ](http://keisuke69.hatenablog.jp/)の記事を加筆修正して転載したものです。
【PHP】PHPをインストールしたらやっておきたい設定


## 前提

CentOS6.5で動作確認をしています。
初心者を想定して記述しているドキュメントとなっています。
開発用サーバとして動かすこと前提に記述しています。
※ 上記初心者対象という事由により、PHPのバージョンはCentOSデフォルトでyum installできるPHP5.3.3を対象にしています。
※ 既に5.3系のPHPがオフィシャルサポート終了になっているのは承知のうえで、設定上の大きな変更はないものに絞って記述しています。


## PHPをインストール

	# yum install php php-devel php-pear php-mbstring php-gd php-mysql php-xml php-mcrypt -y   # php関連の基本ファイルをインストール


## PHPの設定を編集

PHPの設定は/etc/php.iniという設定ファイルによって行われています。
そのため、下記ではphp.iniというファイルを編集することによって、PHPの設定を変更していきます。

### オリジナルphp.iniをバックアップ

	# cp /etc/php.ini /etc/php.ini.origin	# デフォルトで生成されているphp.iniファイルをphp.ini.originというファイル名でコピーファイルを作成

### エラー表示の設定を変更

* error_reportingの設定を変更(513行目あたり)
	error_reporting = E_ALL | E_STRICT (開発環境においてはSTRICTを含めたすべてのレポートをさせる)

* display_errorsの設定を変更(530行目あたり)
	display_errors = On	(エラーがあった際にブラウザなどにエラー内容を表示するように設定）

* log_errorsの設定を変更(551行目あたり)
	log_errors = On	（エラーログを吐く設定を有効にしておく）

* error_logの設定を変更(636行目あたり)
	error_log = /var/log/php.log(phpに関連するエラーログを/var/log/php.logに吐くように設定)


### 文字コード関連の設定

* default_charset = "UTF-8"
* mbstring.language = Japanese
* mbstring.internal_encoding = UTF-8
* mbstring.encoding_translation = Off
* mbstring.http_input = pass
* mbstring.http_output = pass
* mbstring.detect_order = auto


### メモリ管理に関する設定

* memory_limit = 32MB  
PHPの1プロセスが利用可能なメモリー容量の設定。
* post_max_size = 16M
POSTのリクエストを受け付ける際の、最大のPOSTリクエストサイズを設定
* upload_max_filesize = 8M
ファイルアップロードを受け付ける際の、最大のファイル受付サイズを設定


### セキュリティに関する設定

* expose_php = Off  
これがOnだとレスポンスヘッダにPHPのバージョン情報などが露呈してしまう
* session.hash_function = 1  
セッションID発行のハッシュアルゴリズムをSHA-1(160bit)へ変更, 0だとMD5(128bit)。生成されたハッシュを32桁にしたい場合は、併せてsession.hash_bits_per_character = 5とする
* session.entropy_file = /dev/urandom  
  /dev/urandomが存在するときのみ
* session.entropy_length = 32


### その他の設定

* short_open_tag = Off  
PHPファイルのタグを<?php ?>のみ利用可能と制限(<? ?>などを使用不可にする)
* register_argc_argv = On  
バッチのようなコマンドラインプログラムを書く場合は必須の設定
* max_execution_time = 30  
PHPプログラムの１つの最大実行時間の設定。これも大きなファイルアップロードや大きいバッチ処理がある場合はプログラム側のini_set()などで随時設定する


## 変更した設定を読み込み
php.iniでの設定はApacheを再起動することによって再読込されるので、Apacheを再起動します。

	# service httpd restart


## まとめ
上記でPHPをインストールし、開発環境として利用する上での最小限の設定は完了です。
詳細な設定内容についてはより調べていただくか、[『パーフェクトPHP』](http://www.amazon.co.jp/gp/product/4774144371?ie=UTF8&camp=1207&creative=8411&creativeASIN=4774144371&linkCode=shr&tag=knife0125-22)の12章などに詳しいので、参考にしてみてください。
Rustの2015/09/04時点で一番マシなインストール方法

現在Rustのインストール手段は複数提供されています。

* Mac, Windows用のインストーラ (`.pkg`とか`.exe`とか)
* Linux, Mac用のコンパイル済みバイナリ
* ソースコード

ちなみに、バージョンも最新版のnightlyとリリース版がありますが、残念ながら1ヶ月に一回破壊的に変更される世界でリリース版を使う意味はゼロです。常に最新版を向いていたほうがマシです。

さて、上の配布手段でどれを採用するべきか？答えはどれも不正解で下を使うのが楽だ、と[公式も言っています](http://doc.rust-lang.org/guide.html)

```shell-session
$ curl -s https://static.rust-lang.org/rustup.sh | sudo sh
```

でも普通に考えてcurlしたスクリプトをsudoするとか狂気に近いですし、そもそも毎日仕様の変わる言語を`/`以下にインストールするというのもおかしな話です。なので、次のようにしておきましょう。

```shell-session
$ curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --prefix=$HOME/local/opt/rust 
```

`--prefix`以下は本人の好みなので好きなところを指定しておいてください。では楽しいRust生活を！

## 2015-09-04追記
version 1.0リリース以前は上でよかったのですが、最近の`rustup`ではデフォルトでリリース版がインストールされます、がそれじゃ嬉しくないので`--channel`というオプションを追加します

```shell-session
% curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --prefix=$HOME/local/opt/rust --disable-sudo --channel=beta
```

これでbeta版をインストールできますのでこっちをおすすめします[^1]。

[^1]: もっとも、Rust自体リリース済みなわけであまりbetaにこだわらなくてもいいよという開発元のメッセージなのかもしれませんが。
[GAS]実行に失敗: その操作を実行する権限がありません。に悩んだこと


Google Apps ScriptでDebugをしていた際に、EventTriggerで少しハマった件について、メモを残しておきます。
やりたかったことは、Eventを拾ってその情報をLogシートに書き出しておくということ。

##ハマったこと
SpreadsheetApp.openById();
を使った時に
__実行に失敗: その操作を実行する権限がありません。__
というエラーが出ていた。


```
var ss = SpreadsheetApp.openById(SheetID);
```

単体で実行する分には問題なかったのだが、EventTriggerから呼ばれた際に、エラーになっていた。

呼び出し元ソース

```Common.gs
function onEdit(e)
{
  var r = e.source.getActiveRange();
  sample(r);
}

function sample(range)
{
  var useraddress = Session.getActiveUser().getEmail();
  range.setNote("Last modified: " + (new Date()) + "[modified by " + useraddress + "]");
  Log.debug(range.getA1Notation(), range.getValue());
}

function test_sample()
{
  sample(SpreadsheetApp.getActiveSheet().getRange("A1"));
}
```

##単体の呼び出しは問題なし

```Log.gs
var SheetID = PropertiesService.getScriptProperties().getProperty('SPREAD_SHEET_ID');
var LogSheetName = PropertiesService.getScriptProperties().getProperty('LOG_SHEET_NAME');
var Log = {
  debug: function (cell, message) { Log.write('Debug', cell, message); },
  write: function (logLevel, cell, message) {

    var ss = SpreadsheetApp.openById(SheetID);
    var logsheet = ss.getSheetByName(LogSheetName);
    var logValue = new Array();
    logValue = [ 
      logsheet.getLastRow()+1,       // A列
      new Date(),                    // B列
      logLevel,                      // C列
      cell,                          // D列
      message,                       // E列
      Session.getActiveUser().getEmail()
    ];
    logsheet.appendRow(logValue);
  }
};


// unit test
function log_test() {
  Log.debug("A1", "ログ出力");
}
```

log_test()
の実行は問題なし


##Common.gs → Log.gsの参照に何か問題があるのか？
test_sample()
の実行は問題なし。

単体実行では問題なく動く。

どうもSpreadsheetにおいて、onEventからの場合に、setNote()は動作しているのに、Log.debugを呼び出すとopenByIdで止まっている。


##理由はまだ不明だがトリガの設定をすることで解決

リソース＞すべてのトリガー（ちなみに、「現在のプロジェクトのトリガー」でもよいです）
![スクリーンショット 2014-11-20 17.22.22.png](https://qiita-image-store.s3.amazonaws.com/0/31540/4e03f37d-9a30-afb5-aa34-8f420b14cb19.png "スクリーンショット 2014-11-20 17.22.22.png")

![スクリーンショット 2014-11-20 17.24.49.png](https://qiita-image-store.s3.amazonaws.com/0/31540/76ff3382-f2f7-7d69-ae55-e88620002413.png "スクリーンショット 2014-11-20 17.24.49.png")

ここでトリガーを設定する。

![スクリーンショット 2014-11-20 17.25.40.png](https://qiita-image-store.s3.amazonaws.com/0/31540/3eaf39f5-a9eb-e160-7fe1-a0c987894007.png "スクリーンショット 2014-11-20 17.25.40.png")

「保存」すれば問題ありません。

これで、実行するとエラーが無くなりました。



##まとめ
* なぜトリガの設定が必要だったのか
* onEventはトリガを設定しなくても動くのに、SpreadsheetApp.openByIdはなぜ嫌がられたのか

この辺りはまだ調査中です。。。

##GASのデバッグでの参考させていただいた記事

[Google Apps Scriptでデバッグ](http://qiita.com/hokaccha/items/e41012cc3833ae9cbe13)
Viewへつけるタグを文字列で扱いたい


Androidだとタグに文字列(正確にはObjectクラス)を設定できるので、
タグの仕様を決める人と、このタグを利用する人が別々でも、なんとかなるなる。

```Java:タグからViewを呼び出す例(Android)
View title = convertView.findViewWithTag(TITLE);
        if (title instanceof TextView) {
            ((TextView) title).setText("たいとる");
        }
```

iOSで同様のことをやろうとすると、
NSInteger（`- (UIView *)viewWithTag:(NSInteger)tag`）な感じで、都合が悪い。

パッと思いつくのは、UIViewにタグを保持するNSStringのプロパティをカテゴリで追加してしまうこと。

例えば下記みたいな感じ。
[How to identify view with NSString tag? - stackoverflow.com](http://stackoverflow.com/questions/7885955/how-to-identify-view-with-nsstring-tag)

```objectivec:タグをNSStringにしてみた例(iOS)
@interface UIView (StringTagAdditions)
@property (nonatomic, copy) NSString *stringTag;
@end

@implementation UIView (StringTagAdditions)
static NSString *kStringTagKey = @"StringTagKey";
- (NSString *)stringTag
{
    return objc_getAssociatedObject(self, kStringTagKey);
}
- (void)setStringTag:(NSString *)stringTag
{
    objc_setAssociatedObject(self, kStringTagKey, stringTag, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
```

いま、タグ仕様を決める人とタグを利用する人が別々で機能提供を検討しています。

* 全てのUIViewが対象ってわけではない
* UIView自体の機能拡張が目的ではない

こんな状況で最初からカテゴリでプロパティ追加って大げさかなと思い、少し悩んでいるのでメモを残すことにしたった。
brew updateでGitのエラーが出た場合

Mac OSX 10.9.5の場合の話です。
久しぶりにHomebrewのupdateをしようとしたらこんなエラーが出ました。

```ターミナル
$sudo brew update
Password:
error: Your local changes to the following files would be overwritten by merge:
	.gitignore
	.yardopts
	CODEOFCONDUCT.md
	CONTRIBUTING.md
	LICENSE.txt
--省略--
Please move or remove them before you can merge.
Aborting
Error: Failure while executing: git pull -q origin refs/heads/master:refs/remotes/origin/master
```

見たところgitのエラーっぽいので手動で以下を実行

```
$ cd $(brew --prefix)
$ git fetch origin
$ sudo git reset --hard origin/master
```

再度brew updateを実行すると

```
$ sudo brew update
Updated Homebrew from b11f75bf to b11f75bf.
==> Updated Formulae
```

ということで無事に完了しました。
CentOS7でndjbdns1.06を動かす

## 参考

* [N-DJBDNS](http://pjp.dgplug.org/ndjbdns/document.html)
* [Installing NDJBDNS on CentOS 6.4 | n40lab](http://n40lab.wordpress.com/2013/07/04/installing-ndbjdns-on-centos-6-3/)

## 手順

192.168.0.50で以下作業実施

```bash:
yum install -y ndjbdns bind-utils
cd /etc/ndjbdns
cat > data <<...
## +       : lookup domainname -> ip
## ^ PTR   : lookup ip -> domainname
## C CNAME : alias
##
## @ mx    : smaller num is high priority
## ' txt   : spf record
...
```

```bash:
tinydns-edit data data.new add ns 0.168.192.in-addr.arpa 127.0.0.1
tinydns-edit data data.new add ns dns.local 192.168.0.50
tinydns-edit data data.new add host dns.local 192.168.0.50
tinydns-edit data data.new add host repository.local 192.168.0.51
tinydns-edit data data.new add host www.local 192.168.0.52
```

```bash:dataからdata.cbdを生成
tinydns-data
```

```bash:サービス登録
systemctl enable tinydns
systemctl start tinydns
```

```bash:動作確認
dig repository.local @127.0.0.1
```


# 外部から問い合わせを受け入れる

* tinydnsが動作しているサーバのIPを192.168.0.50とする。

```diff:tinydns.conf
- IP=127.0.0.1
+ IP=127.0.0.1,192.168.0.50
```

```bash:
systemctl restart tinydns
```

動作確認

```bash:
dig repository.local @192.168.0.50
```

dataを編集後は`tinydns-data`を実行するだけでよい。
(tinydnsのrestartは不要)


続きは[ndjbdnsのマニュアルにない書式 - Qiita](http://qiita.com/tukiyo3/items/91799f6a931b56dcd7d4)