OmniAICreator/Qiita-1.07M huggingface dataset:
Docker for MacでAmazon Linuxを動かしてみる


## 条件
* Mac OS Sierra
* Docker for Macをインストール
* [Docker Hub](https://hub.docker.com)にサインアップ

## Hello World

### Docker Hubにログイン

```
$ docker login
```

Docker Hubのユーザーネームとパスワードでログインする。


### Hello Worldを実行する

まずはお手本通りHello Worldを実行する。

```
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
78445dd45222: Pull complete 
Digest: sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://cloud.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/
```

Hello Worldの最新イメージがpullされてコンテナとして実行された。（Hello World用のイメージがDockerHubに存在する）

### Amazon Linuxを動かす

Amazon Linuxのイメージをpullする。

```
$ docker pull amazonlinux
Using default tag: latest
latest: Pulling from library/amazonlinux
0793c64286b7: Pull complete 
Digest: sha256:7c781c9234e712f135ee402a13ffd5dbf342a9ff1394c73bc5ae4d9b9078e0f8
Status: Downloaded newer image for amazonlinux:latest


# pullしたイメージを確認

$ docker images
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
amazonlinux            latest              766ebb052d4f        6 weeks ago         162 MB
```


イメージからコンテナを作成して起動する。

```
$ docker container run -itd amazonlinux

#起動中のコンテナを確認する
docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
cc02297dc8f1        amazonlinux         "/bin/bash"         About a minute ago   Up About a minute                       peaceful_ritchie
```

起動したコンテナにアクセスする。

```
$ docker attach cc02297dc8f1
bash-4.2# 

# exitコマンドを打つとコンテナを停止して終了
bash-4.2# exit
exit
```

先ほど作成したコンテナを起動して今度は終了させないで抜けてみる。

```
$ docker start cc02297dc8f1
cc02297dc8f1

# もう一度アクセス
$ docker attach cc02297dc8f1
bash-4.2# 


# Control + p + q

# コンテナが起動中であることを確認する

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
cc02297dc8f1        amazonlinux         "/bin/bash"         19 minutes ago      Up 3 minutes                            peaceful_ritchie

```

コンテナを終了する。

```
$ docker stop cc02297dc8f1
cc02297dc8f1
```
Java8でAnnotationを動的に差し替えたい時

## 背景

あまりよくある話ではありませんが、@Data(key="1")のようなアノテーションが設定されているクラスについて、動的に@Data(key="2")に変更したい場合があります。

## 解決策

Java8では、そのような場合の追加機能があるようで、以下のサイトを参考にしました。

* https://rationaleemotions.wordpress.com/2016/05/27/changing-annotation-values-at-runtime/

## もう少しシンプルに

```java
public class DynamicAnnotationReplaceUtils {
    private static final String ANNOTATIONS = "annotations";
    private static final String ANNOTATION_DATA = "annotationData";

    /**
     * 特定のクラスのアノテーションを、別のアノテーションに置き換えます。
     *
     * @since
     *
     * @param targetClazz 置換対象のアノテーションを設定しているクラスです。
     * @param originalOne 置換元のアノテーションです。
     * @param newOne 置換先のアノテーションです。置換元のアノテーションをextednsしたクラスのインスタンスになる事が多いでしょう。
     */
  public static void annotationReplacedBy(Class<?> targetClazz, String originalName, Annotation newOne) {
        try {
            @SuppressWarnings("all")
            Method method = Class.class.getDeclaredMethod(ANNOTATION_DATA, null);
            method.setAccessible(true);

            Object annotationData = method.invoke(targetClazz);

            Field annotations = annotationData.getClass().getDeclaredField(ANNOTATIONS);
            annotations.setAccessible(true);

            @SuppressWarnings("unchecked")
            Map<Class<? extends Annotation>, Annotation> map =
                    (Map<Class<? extends Annotation>, Annotation>) annotations.get(annotationData);

            Annotation original = map.entrySet().stream().filter(e -> {
                return e.getKey().getSimpleName().equals(originalName());
            }).findFirst().get().getValue();

            if (original == null) {
                throw new IllegalArgumentException(
                        String.format("Class(%s) has not %s annotaion.",
                                targetClazz.getCanonicalName(), originalName));
            }

            map.put(original, newOne);
        } catch (Exception ex) {
            throw new IllegalArgumentException(ex);
        }
    }
```
## 利用方法

```java
DynamicAnnotationReplaceUtils.annotationReplacedBy(AnnotatedCalss.class, "Data", new ReplacedData()), 
```

## 置換先のアノテーションは?

### 置換元アノテーションの定義

```java
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Data {
    public abstract String key();
}
```
### 置換先アノテーションの定義

```java
public ReplacedData implements Data {
    public  String key() {
         return "2";
    }
}
```

### 置換元アノテーションが付与されたクラス

```java
@Data(key = "1")
public TestData() {
}
````
Gitでブランチ名をサクッと3つの変える手順

 単なる備考録です。お役に立てれば。

### 1.ローカルのブランチ名を新しく変更する

```terminal
$ git branch -m old_branch new_branch
```

### 2.古い方のリモートのブランチを削除する

```terminal
$ git push origin :old_branch
```

### 3.変更済の新しいローカルブランチをリモートにpushする

```terminal
$ git push origin new_branch
```

最後に`$ git branch -a`でブランチの一覧をチェックする。

ちなみに現在いるブランチ名(old_branch)を変更する場合は
`$ git branch -m new_branch`とすればOK。
Jquery初心者がもぐら叩きゲームを作成する　#2

プログラミングでの転職を目指しており、Jqueryから、まず勉強しております。
昨日の続きです。


```javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>もぐら</title>
</head>
<body>
<!--画面表示部分--------------------------------------------------->
<p>もぐら叩きだお</p>
<p>SCORE:</p>


<!--もぐら表示--->
<!-- <a href="javascript:;" id="mogu1"><img src="./pict/"></a>　-->
<!-- <a href="javascript:;" id="mogu1"><p>もぐら</p></a> -->

<!-- <a href="javascript:;" id="mogu1"><img src="./pict/mogura-illust8.png"></a> -->
<!--　<a href="javascript:;" id = "hit"><img class = "mogu1" src="./pict/mogura-illust8.png"></a>　-->
<!--テスト用コード-->
<a href="javascript:;" id = "hit1"><img class = "mogu1" src="./pict/mogura-illust7.png"></a>
<a href="javascript:;" id = "hit2"><img class = "mogu2" src="./pict/mogura-illust7.png"></a>
<a href="javascript:;" id = "hit3"><img class = "mogu3" src="./pict/mogura-illust7.png"></a>

<!--テスト用コード2-->
<div id = "hitTest">
  <button>
    <img class = "moguTest" src="./pict/mogura-illust7.png">
  </button>
</div>


<!--Jqueryの読み込み　--------------------------------------------->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
//TODO　まずはもぐらが表示されることを目標にする

//もぐらが出ている画像をセット
/*
var mogu_img = "./pict/mogura-illust7.png"

console.log(mogu_img);

$('.mogu1').attr({
  'src':mogu_img
});
*/

//もぐらランダム表示処理


//TODO　次にもぐらが叩かれて消えることを目標にする
//もぐらが叩かれている画像をセット
var　moguHit_img = "./pict/mogura-illust10.png"
//もぐらが隠れている画像をセット
var　hole_img = "./pict/mogura-illust8.png"
console.log(hole_img);

$('#hit1').click(function() {
  console.log(1);
  //もぐらが叩かれている画像を表示
  $('.mogu1').attr({
    'src':moguHit_img
  });
  //
  setTimeout(function(){
    $('.mogu1').attr({
      'src':hole_img
  })},500);
});

$('#hit2').click(function() {
  console.log(1);
  //もぐらが叩かれている画像を表示
  $('.mogu2').attr({
    'src':moguHit_img
  });
  //
  setTimeout(function(){
    $('.mogu2').attr({
      'src':hole_img
  })},500);
});

$('#hitTest').click(function() {
  console.log(1);
  //もぐらが叩かれている画像を表示
  $('.moguTest').attr({
    'src':moguHit_img
  });
  //
  setTimeout(function(){
    $('.moguTest').attr({
      'src':hole_img
  })},500);
});



</script>
</body>
</html>

```
No route matches [POST] のエラー　解決法

### エラーの概要
No route matches [POST] のエラー　解決法


![screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/167576/0e048453-549a-f559-84f3-52f7127616a4.png)

chat_roomsモデルでshow.html.erbでエラーが起きている


rake routesをすると以下で出てくる。

```ruby:

 chat_rooms GET    /chat_rooms(.:format)          chat_rooms#index
                         POST   /chat_rooms(.:format)          chat_rooms#create
           new_chat_room GET    /chat_rooms/new(.:format)      chat_rooms#new
               chat_room GET    /chat_rooms/:id(.:format)      chat_rooms#show
                    root GET    /                              chat_rooms#index



```

###　自分の失敗した点

自分は、 chat_room GET    /chat_rooms/:id(.:format)      chat_rooms#showがあるから、いまいちわからない。

get とpostは、違う点に気づいた。４つのHTTPメソッドの「GET」「POST」「DELETE」「PUT」を使うこと

詳しい説明のリンク
http://www.rubylife.jp/rails/routing/index5.html

###  エラーの解決
postのルートを作る。

```ruby:routes.rb
post 'chat_rooms/:id' => 'chat_rooms#show'
```

作った解決する
ZABBIX: 障害情報をmattermostに書き込む

# 目的

zabbixにて障害が発生した場合、Mattermostに障害情報(ITEM.VALUE)を書き込む。

# やったこと

Zabbixで障害が発生すると、Zabbixのアクション機能で、リモートコマンド(webhook)を実行し、以下のようにMattermostに障害情報を書き込む。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/652f469b-2b26-3dfa-615e-9d29e73a27ae.png)



# 事前にいるもの

+ zabbix(当環境は3.0)
+ Mattermost

# 作業の流れ

1. Mattermostの「内向きのウェブフック」設定
2. zabbixのitem/trigger設定
3. zabbixのアクション設定
4. zabbixサーバ側でのスクリプト設定

# 作業の流れ(詳細)
### Mattermostの「内向きのウェブフック」設定
#### Mattermost内で「統合機能」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/3c153102-f9f7-717f-606b-8fcbce742947.png)
#### 「内向きのウェブフック」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/e17c23a3-823a-c470-d55a-61c183cba979.png)
#### 「内向きのウェブフックを追加する」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/02e9f7ff-2fe1-a130-2334-d9c042663ca5.png)
#### 必要情報を記載（重要なのはどこのチャンネルに書き出すか(ここではchannel=alert))
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/b0bb1dd2-3111-d009-7ad3-4a8960a565b4.png)
#### 設定完了すると、下記のようにTOKENを含んだアクセスURLが出てくるので控えておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/30cb9eb6-5851-5b34-1751-2d83835012da.png)

+ TOKEN丸見えですが、どうせすぐスクラップするので載せてます（載せたほうがサンプルPGMも分かり易そうだし）

### zabbixのitem/trigger設定
割愛します。何かアラートが上がるような設定をします。

### zabbixのアクション設定
#### アクション部分は、名前だけ設定します(ここでは"send mattermost")
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/d46cf1b9-ed66-3a9b-7f40-3b46551a6886.png)
#### アクションの実行条件もデフォルトのままでOKです
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/5b38d67e-2632-af28-8e76-e0a4a55d1c3b.png)
#### アクションの実行内容

+ 実行内容のタイプ=リモートコマンド
+ ターゲットリスト=現在のホスト
+ タイプ=カスタムスクリプト
+ 次で実行=Zabbixサーバー
+ コマンド=/usr/local/bin/send_mattermost.sh  '{ITEM.VALUE}'

![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/9510da58-2cb7-1b3b-66ea-f1cd14918932.png)

### zabbixサーバ側でのスクリプト設定
雑なプログラムですが、一応動くのでご容赦を…

```ruby:/usr/local/bin/send_mattermost.sh
#!/usr/bin/php
<?php
$json = json_encode( array( "text" => preg_replace( "/^[^ ]* /", "Alert ", implode( " ", $argv))));

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://192.168.10.189:8065/hooks/53yph6toibgyjmqn8ie7aawb3r");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_exec ($ch);
curl_close ($ch);
```

### まとめ
slackを使っていたけど、クローズドな環境でchatを使いたくて、Mattermostをインストールした。
初めて使ってみたけど、Mattermostはいい感じかも。
今後、どうやってやるか知らないけど、Mattermostでクローズって呟いたら対象の障害イベントのコメント記載しクローズするようなの作ってみたい。
Webページにappear.inを埋め込む方法


以下のIFrameを埋め込むと、該当するルームにWebからいつでも入れるUIを提供できます。

```
<iframe src="https://appear.in/your-room-name" width="800" height="640" frameborder="0"></iframe>
```

↑your-room-name を 任意のルーム名に変更する
appear.in で Lockを活用する


Lockは、ゲストユーザがルームに入室を試みる際に、knockを必要とする設定です。
ゲストユーザが意図したユーザかどうかをチェックした上で入室を許可することができます。

## Lockを有効にする
- 画面上部の Lock ボタンをクリックする。
![appear_lock_1.png](https://qiita-image-store.s3.amazonaws.com/0/6311/fffd16d0-25b5-37af-ff42-8d3b92fd4b6b.png "appear_lock_1.png")

- ルームのLockが有効になります。
![appear_lock_2.png](https://qiita-image-store.s3.amazonaws.com/0/6311/3ae15e73-3bba-d3da-1a78-4314e690604d.png "appear_lock_2.png")

## ゲストユーザを確認する
- Lockを有効にした後、ゲストユーザが入室しようとした場合、knockを促す画面が表示されます。
![appear_lock_3.png](https://qiita-image-store.s3.amazonaws.com/0/6311/34b2392a-03cd-db4c-651d-c3a60cf99843.png "appear_lock_3.png")

- knockをクリックすると、ルームに通知が届きます。
![appear_lock_4.png](https://qiita-image-store.s3.amazonaws.com/0/6311/40ffc168-fdc1-f7a6-dd98-85722a942739.png "appear_lock_4.png")

- 通知のLet inをクリックすると、ゲストユーザの入室を許可します。
- 通知のSee whoをクリックすると、入室しようとしているゲストユーザを確認できます。
![appear_lock_5.png](https://qiita-image-store.s3.amazonaws.com/0/6311/70c37294-528b-b4fb-51c4-357539202f33.png "appear_lock_5.png")

- ゲストユーザの確認画面で Let inをクリックすると、ゲストユーザの入室を許可します。
- ゲストユーザの確認画面で Put on hold をクリックすると、入室を保留(This person is on hold)できます。
![appear_lock_6.png](https://qiita-image-store.s3.amazonaws.com/0/6311/8eea83e6-fda1-f905-0059-00144508a049.png "appear_lock_6.png")

- ゲストユーザの確認画面で Rejectをクリックすると、入室を拒めます。
- 入室を拒まれたゲストユーザにはその旨通知されます。
![appear_lock_7.png](https://qiita-image-store.s3.amazonaws.com/0/6311/024ea8d9-8173-30db-6626-cbf3854f2784.png "appear_lock_7.png")

- 入室を拒まれたゲストユーザは入室を認めてもらうよう頑張りましょう。

## Lockを無効にする
- 画面上部の Locked ボタンをクリックする。
- ルームのLockが無効になります。

## どんなときに使うか
- 定期的に利用するルームでセキュリティ上入室制限をかけるようなとき
appear.in は URLがわかれば自由に入室できてしまうので、ありきたりなURLだとうっかり入室してくる人がいるかもしれない（一度経験あり ◯◯-testとかありがち）
- 採用面接等で後悔したURLで入室を待つとき

そもそも、URLをランダムな英数字（パスワードみたい）で設定すれば一意性は高められると思う
新しいmacにbrewを使ってawscliをインストール

awsを使うための設定をした。configureファイルも流れで作成されたのでそのメモ。

# awscli
覚えたてのbrew searchを使ってコマンド名を確認してからインストール。configureファイルも合わせて作成された。

```console
$ brew search aws
aws-apigateway-importer  aws-elasticache          aws-sdk-cpp              awslogs
aws-as                   aws-elasticbeanstalk     aws-shell                kube-aws
aws-cfn-tools            aws-keychain             aws-sns-cli              yaws
aws-cloudsearch          aws-mon                  awscli

$ brew install awscli

$ aws --version
aws-cli/1.11.91 Python/2.7.10 Darwin/16.4.0 botocore/1.5.54

$ ls -1 ~/.aws
config
credentials
```

無事インストールできました。

以上
RxJavaのdoAfterNextを使う

https://twitter.com/mapyo/status/867340952167268352

```
RxJavaで一つ前の川で受信用のobservableをflatmapとかで設定して、その直後で送信処理するみたいな事書きたい
```

こういう事がしたかった。

http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Observable.html#doAfterNext(io.reactivex.functions.Consumer)

doAfterNextを使うと解決出来そうだった。サンプルコードはこちら
publishSubject.onNextのとこらへんで送信開始処理みたいなのを行うイメージ

```kotlin
        val publishSubject = PublishSubject.create<Int>()

        Observable.just(1)
                .doAfterNext {
                    println("doAfterNext")
                    publishSubject.onNext(it * 2)
                }
                .flatMap {
                    println("receive start")
                    publishSubject
                }
                .subscribe({ println(it) })
```

出力結果はこちら

```
receive start
doAfterNext
2
```


1. flatMapでpublishSubjectが設定される
2. その後doAfterNextが呼ばれて、publishSubjectで1 * 2が流される
3. subscribeしてるところで２がとれる


という事で無事に出来ました。もうちょっと早く気がついてたらもっといい川を書けてたかもしれない。
MacでJavaのバージョンを切り替える方法

いろんなサイトに方法がかかれているのに毎回やり方を勘違いするという現象が起こるので自分でもまとめます。

:computer:環境:computer:

- OS : macOS Sierra Version 10.12.4
- 現在使っているJava

```text
$ java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
```

- インストールしてあるJava
    - [MacでインストールされているJavaを確認する方法 - Qiita](https://qiita.com/ponsuke0531/items/0506d41e355a585ccc97)

```text
$ /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java_home -V
Matching Java Virtual Machines (5):
    1.8.0_131, x86_64:  "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home
    1.8.0_45, x86_64:   "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home
    1.7.0_67, x86_64:   "Java SE 7" /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home
    1.6.0_65-b14-468, x86_64:   "Java SE 6" /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    1.6.0_65-b14-468, i386: "Java SE 6" /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home
```
バージョンを「1.8.0_45」から「1.7.0_67」に切り替えます。

### 1 .bashrcに追記する。
.bashrcに「JAVA_HOMEの設定」と「PATHにJAVA_HOMEの追加」の2行を追記します。

```text
$ sudo vi .bashrc
Password:{パスワード}

---ここからviエディタ------------------------------------------
<ここにはズゥっと前に書いた設定が書かれています>
export JAVA_HOME=`/System/Library/Frameworks/JavaVM.framework/Versions/A/Commands/java_home -v "1.7"`
PATH=$JAVA_HOME/bin:$PATH
---ここまでviエディタ------------------------------------------
```
こちらのサイト様に感謝です。
> .profile, .bashrc, .zshrcなどなんでもいいですが，環境変数JAVA_HOMEをjava_homeコマンドを使って設定します．
> [OSXでJavaのバージョンを切り替える - Qiita](http://qiita.com/ringo/items/db58b34dc02a941b297f)

### 2 .bashrcを再読込する。
コレをやらずに「切り替えられない:confounded:」と毎回勘違いしています。
設定ファイルを書いたら再読込は基本ですよね。

```text
$ source ~/.bashrc
```

こちらのサイト様に感謝です。
> 追加したらsource ~/.bash_profileで再読み込みするとバージョンが切り替わります。
> [MacでHomebrewを使用して複数バージョンのJava (JDK) をインストールして切り替える方法＋アップデート - TASK NOTES](http://www.task-notes.com/entry/20150406/1428289200)

### 3 確認する。
切り替わっていることを確認します。

```text
$ java -version
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
```
新しいmacにbrewを使ってjavaとmavenをインストールする

macを新調したので、javaの環境を整えた時のメモ。macに馴れ親しむことも目的に、brewを使ってインストール。

# brew
https://brew.sh/index_ja.html にある通り。Xcode Command Line Toolsも同時にインストールできる。

```console
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
$ brew -v
Homebrew 1.2.1
```

# java
caskを使って最新のバージョンのjavaがインストール。現時点だとjava8。特にこだわりはないのでそのまま。その後環境変数なども設定。

```console
$ brew cask install java
$ java -version
java version "1.8.0_131"
$ javac -version
javac 1.8.0_131
```

参考
http://qiita.com/yanap/items/186d5bd1118f68f725d8
http://qiita.com/yu-iskw/items/79d9bddb77efaf2ca255

# maven
以下のコマンドで最新のmavenをインストール。

```console
$ brew install maven
$ mvn -v
Apache Maven 3.5.0 (ff8f5e7444045639af65f6095c62210b5713f426; 2017-04-04T04:39:06+09:00)
```

参考
http://qiita.com/hoisjp/items/d5fd6d96235e2f2fdedb

以上
Mac + DMD の環境で ld: warning: pointer not aligned at address が発生する

Xcode 8.3 にアップデートした後、 dmd 2.074.0 でコンパイルしたコードを実行すると、以下のようなエラーが出ます(LDCや古いDMDでは発生しません)。

```
ld: warning: pointer not aligned at address 0x10009CD46 (_D25TypeInfo_AxS5hello6Sample6__initZ + 16 from hello.o)
ld: warning: pointer not aligned at address 0x10009CD36 (_D25TypeInfo_AxS5hello6Sample6__initZ + 0 from hello.o)
ld: warning: pointer not aligned at address 0x10009CD5E (_D12TypeInfo_Hib6__initZ + 16 from hello.o)

(略)

ld: warning: pointer not aligned at address 0x1000ABCB9 (_D3std8datetime13PosixTimeZone6__vtblZ + 32 from /Library/D/dmd/lib/libphobos2.a(datetime_465_53e.o))
ld: warning: pointer not aligned at address 0x1000ABCA1 (_D3std8datetime13PosixTimeZone6__vtblZ + 8 from /Library/D/dmd/lib/libphobos2.a(datetime_465_53e.o))
ld: warning: pointer not aligned at address 0x1000ABCC9 (_D3std8datetime13PosixTimeZone6__vtblZ + 48 from /Library/D/dmd/lib/libphobos2.a(datetime_465_53e.o))
```

ひとつの回避策は LDC を使うことですが、この問題は既に修正されているので、まだベータ版ではありますが [dlang.org のダウンロードページ](https://dlang.org/download.html) から DMD Beta 2.074.1-b1 をインストールすることで解決します。

参考: [With Xcode 8.3 linker, warnings of "pointer not aligned"](https://issues.dlang.org/show_bug.cgi?id=17289)
Servlet 3.x環境のSpring SecurityでHttpServletRequest#loginでログイン

ぐぐると使用例として、例えば、ユーザ登録完了後にそのままログインさせる、というケースがある。この場合、ユーザがフォームなどで明示的にIDとパスワードを入力するのではなく、プログラム的にログインする方法になる。

これの実現には、Servlet 3.0以上では、Spring Securityを設定した上で[HttpServletRequest#login (Java(TM) EE 7 Specification APIs)](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html#login-java.lang.String-java.lang.String-)を呼ぶ。

```java
@RequestMapping(...
public void index(HttpServletRequest request) {
    try {
        request.login("username", "password");
    } catch (ServletException e) {}
}
```

[Spring Security Reference - 15.2.2 HttpServletRequest.login(String,String)](http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#servletapi-login)にあるとおり、Spring SecurityとServlet APIの連携機能によるもの。仕組みとしては、loginメソッドを呼ぶと裏側で現在有効な```AuthenticationManager```を使用してログイン処理が行われる、というのようだ。

2021/01/09 追記

他の方法として```AbstractPreAuthenticatedProcessingFilter```もある。https://kagamihoge.hatenablog.com/entry/2020/08/02/171003
docker-composeでOS起動時にコンテナを自動起動する方法

docker単体でOSの起動時にコンテナを起動させる際には
`docker run --restart=always redis`
といった風に--restart=alwaysとオプションを追加します。
[公式ドキュメント](https://docs.docker.com/engine/reference/run/#restart-policies---restart)
[公式ドキュメントの日本語翻訳版(少しバージョンが古いかも)](http://docs.docker.jp/engine/reference/run.html#restart-policies-restart)
けど、docker-composeを使う場合はどうすればいいのかわからなくて少し調べたので書きます。

といってもdocker-compose.ymlに1行追加するだけだった

``` docker-compose.yml
# jenkins
jenkins:
  image: jenkins
  ports:
    - "8080:8080"
  volumes:
    - /root/docker/jenkins/jenkins_home:/var/jenkins_home
  # ここを追加
  restart: always
# ui_for_docker
ui-for-docker:
  image: uifd/ui-for-docker
  ports:
    - "9001:9000"
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock
  # ここを追加
  restart: always
```
ipywidgetsでWebアプリっぽく遊ぶ

# ipywidgets とは

Jupyter notebook 上でインタラクティブなウィジェット（ラジオボタン、チェックリスト等）を表示、コントロールできるモジュール。どれくらい簡単にできるかやってみた。

- https://github.com/jupyter-widgets/ipywidgets

# ToDo リスト

Webアプリ練習の定番。結構簡単。
https://gist.github.com/emakryo/98142e8f5b02206ada660879f935139f

Chromeだとこんな感じ。

![スクリーンショット 2017-05-24 20.55.57.png](https://qiita-image-store.s3.amazonaws.com/0/99967/9a0b2c85-294c-45bb-6221-4a27683a5997.png)

gistとかnbviewerだとHTMLの出力は表示されないのが残念です。

# 以上

jupyter上だとデバッグが簡単で良い。
参考にしたのは本家の[examples](https://github.com/jupyter-widgets/ipywidgets/tree/master/docs/source/examples)。
bokehとは相性良さそうでデータの可視化とかすごい捗りそう。

- http://bokeh.pydata.org/en/latest/docs/user_guide/notebook.html
- http://qiita.com/driller/items/0730325bf5c1cd689979
jsdoでconvnetjs その11

#概要
convnetjsで、101から255までの偶数を学習させて、1から100まで聞いてみた。

#結果


```
1 : odd 2 : even 3 : odd 4 : even 
5 : odd 6 : even 7 : odd 8 : even 
9 : odd 10 : even 11 : odd 12 : even 
13 : odd 14 : even 15 : odd 16 : even 
17 : odd 18 : even 19 : odd 20 : even 
21 : odd 22 : even 23 : odd 24 : even 
25 : odd 26 : even 27 : odd 28 : even 
29 : odd 30 : even 31 : odd 32 : even 
33 : odd 34 : even 35 : odd 36 : even 
37 : odd 38 : even 39 : odd 40 : even 
41 : odd 42 : even 43 : odd 44 : even 
45 : odd 46 : even 47 : odd 48 : even 
49 : odd 50 : even 51 : odd 52 : even 
53 : odd 54 : even 55 : odd 56 : even 
57 : odd 58 : even 59 : odd 60 : even 
61 : odd 62 : even 63 : odd 64 : even 
65 : odd 66 : even 67 : odd 68 : even 
69 : odd 70 : even 71 : odd 72 : even 
73 : odd 74 : even 75 : odd 76 : even 
77 : odd 78 : even 79 : odd 80 : even 
81 : odd 82 : even 83 : odd 84 : even 
85 : odd 86 : even 87 : odd 88 : even 
89 : odd 90 : even 91 : odd 92 : even 
93 : odd 94 : even 95 : odd 96 : even 
97 : odd 98 : even 99 : odd 100 : even 
```


#サンプルコード



```
function toarray(n) {
    var ary = new Array;
    for (var i = -1 ; i < 7; i++)
    {
        var s = 1;
        if (i > -1) s = 2 << i;
        var b = n & (s)
        if (b > 0)
        {
            ary.push(1.0);
        }
        else
        {
            ary.push(0.0);
        }
    }
    return ary;
}
function oe(n) {
    if (n % 2 == 0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
function odd(j, w) {
    var str = "";
    if (w[1] > 0.9)
    {
        str = "even";
    }
    else if (w[0] > 0.9)
    {
        str = "odd";
    }
    return str;
}
function test() {
    var str = "";
    var net = new convnetjs.Net();
    net.makeLayers([{
        type: 'input', 
        out_sx: 1,
        out_sy: 1,
        out_depth: 8
    }, {
        type: 'fc', 
        num_neurons: 10,
        activation: 'tanh'
    }, {
        type: 'softmax', 
        num_classes: 2
    }]);
    var trainer = new convnetjs.Trainer(net);
    var avloss = 0.0;
    for (var i = 0; i < 100; i++) 
    {
        for (var j = 101; j < 256; j++) 
        {
            var point = new convnetjs.Vol(1, 1, 10);
            point.w = toarray(j);   
            var f = oe(j);
            var stats = trainer.train(point, f);
            avloss += stats.loss;
        }
    }
    avloss /= 100 * i;
    alert(avloss);
    for (var j = 1; j < 101; j++) 
    {
        var point = new convnetjs.Vol(1, 1, 10);
        point.w = toarray(j);   
        var prediction = net.forward(point);
        str += j + " : "+ odd(j, prediction.w) + "    ";
        if (j % 4 == 0) str += "<br>";
    }
    return str;
}
var a = test();
document.getElementById('helloWorld').innerHTML = a;

```


#成果物
http://jsdo.it/ohisama1/GdsX
SQLで同一グループの中で最大/最小のレコードを取得する


### やりたいこと

同じカテゴリの中での最高値の商品を、1件ずつ取得したいみたいなやつ。

下の例でいうと ★ のレコードを抽出したい。


![sql_1.png](https://qiita-image-store.s3.amazonaws.com/0/18743/832bc4ba-26d8-8feb-1f30-c231801db816.png "sql_1.png")




### 1. テーブル作ってデータ入れる

```
create table items (
  id int not null primary key,
  name varchar(100),
  price int,
  category varchar(100)
);

insert into items values(1, 'りんご', 190, 'くだもの');
insert into items values(2, 'みかん', 100, 'くだもの');
insert into items values(3, 'きゅうり', 80, '野菜');
insert into items values(4, '人参', 110, '野菜');
insert into items values(5, 'キャベツ', 110, '野菜');
insert into items values(6, '豚肉', 300, '肉');
insert into items values(7, '牛肉', 400, '肉');
```


### 2. カテゴリ毎に一番高い価格を抽出する

```sql
select category, max(price) as price from items group by category;
```

結果

![sql_2.png](https://qiita-image-store.s3.amazonaws.com/0/18743/ee05c12a-539b-8993-b699-cebb1f77524d.png "sql_2.png")



### 3. 次に、それらのカテゴリ、価格の中で、一番小さい id を取得する。

サブクエリ使う。

```sql
select 
    category, price, min(id) as id
from 
    items 
where 
    (category, price) 
    in
    (
        select 
            category
            ,max(price) as price 
        from 
            items 
        group by 
            category
    )
group by
    category, price
;
```

結果


![sql_3.png](https://qiita-image-store.s3.amazonaws.com/0/18743/389ae486-3fad-e75e-e76f-fab7de88de62.png "sql_3.png")

### 4. あとは、その id で items を抽出する。

さらにサブクエリ。重そう。

```sql
select 
    * 
from 
    items
where 
    id in (
        select 
            min(id) as id 
        from 
            items 
        where 
            (category, price) 
            in
            (
                select 
                    category ,max(price) as price 
                from 
                    items 
                group by category
            )
            group by category, price
    )
;
```

結果

![sql_4.png](https://qiita-image-store.s3.amazonaws.com/0/18743/ccd55006-9c98-1c73-b7a5-871eb5767479.png "sql_4.png")



おしまい。

もっと簡単にやる方法ないだろか。
プロキシサーバを串させているか、サクッと確認する！(HTTPS, HTTP)

プロキシサーバの設定をサクッと確認するとき、PCのプロキシの設定を変えてもいいけれど・・・？

【例】[PROXY_IP]プロキシサーバIP, [PORT]プロキシポート, [DOMAIN]ドメイン
HTTP
``$ wget -e HTTP_PROXY=[PROXY_IP]:[PORT] http://[DOMAIN]/ip.php``

HTTPS
``$ wget -e HTTPS_PROXY=[PROXY_IP]:[PORT] https://[DOMAIN]/ip.php``



【具体例】
HTTP
``$ wget -e HTTP_PROXY=49.212.221.27:3128 http://yasuken1990.com/ip.php``

HTTPS
``$ wget -e HTTPS_PROXY=49.212.221.27:3128 https://hobby.yasuken1990.com/ip.php``


```ip.php
<?php
echo $_SERVER["REMOTE_ADDR"] ;
```

cat して、プロキシサーバのIPが表示されたらOK!
``$ cat ip.php //49.212.221.27``


下記しばらくそのままにしておくのでご自由にお使いください。
http://yasuken1990.com/ip.php
https://hobby.yasuken1990.com/ip.php

※具体例のプロキシサーバは、各々の環境に合わせてください。
【memo】gem 'kaminari'

kaminariを実装することで簡単にページネーションを作成することが出来る。

インストール編

①GemFile
gem 'kaminari'

②bundle install

実装編
■pageメソッド

kaminariを導入すると、モデルクラスにpageメソッドが定義される。このメソッドは、ページネーションにおけるページ数を指定。
ビューのリクエストの際paramsの中にpageというキーが追加されて、その値がビューで指定したページ番号となる。
よって、pageの引数はparams[:page]となる。

■perメソッド

perメソッドもpageメソッドと同様、kaminariというgemをインストールすることで利用できるメソッド。
1ページあたりに表示する件数を指定。perメソッドに引数として渡した数字が、ページネーションが実装されたビューで1ページあたりに表示する件数になる。

変数名 = クラスを利用して取得したレコードのインスタンス.page(params[:page]).per(ここに1ページで表示したい件数を入力)
※ページネーションを実装したいcontroller#actionに追加

Ex.10件を1ページに表示させる
@twitter = Twitter.order("created_at DESC").(params[:page]).per(10)
[Linux]ファイルの拡張属性に設定されたSELinuxのセキュリティコンテキストを削除する

## 実行したいこと
CentOS6以降で、SELinuxを無効にする前から存在したファイルにはファイルのパーミッションにドット"."がついたままなので、削除する

### 実行するコマンド
rootユーザーで以下のコマンドを実行する

```
指定したファイルのSELinuxセキュリティコンテキストを削除する場合、以下のコマンドを実行する
# setfattr -x security.selinux {ファイル名}

カレントディレクトリ以下で、複数のファイルに対し一括で実行したい場合は、以下のコマンドを実行する
# find . -exec setfattr -x security.selinux {} \;
```

### 参考URL
以下の記事を参考にしました
http://tkak.hatenablog.com/entry/2013/01/04/151248
An error occurred during the file system check


## TL;DR
サーバを起動したら `An error occurred during the file system check` というエラーが出たので root ログインして `fsck` したらとりあえず治った。

## Zabbix からアラート
とりあえず状態を確認する必要があるので ssh したところ応答が来なかった。
ping を投げてみるとどうやら通るので、ネットワークは生きてるし、サーバ自体は起動しているらしい。 

## 現地作業
### 外観観測
遠隔での操作は無理だったので現地に向かい、サーバを確認してみる。
電源ランプは付いているが、 HDD のアクセスランプは明滅していない。
LAN のランプは時折光っている。

### 接続
とりあえずディスプレイとキーボードを接続してみる。
しかしキーボードが認識されない。
ディスプレイもノーシグナルの表示。

### 検討
最初に確認した段階で HDD に障害がありそうだと直感していたので、2つのシナリオを検討した。

* シャットダウンし HDD を持ち帰り、別なマシン上でマウントしてデータを取り出す
* 電源長押し再起動

持ち帰りを選択した場合はシステムの復旧率は上がるが、復旧の時間は非常にかかる。
また、マウントしてデータが読み出せなければ、データ復旧業者等を利用しなければならないので、金銭的にも時間的にもコストがかさむ。

一方電源長押しすれば、再起動するかもしれない。
実際のところサーバが不調だった時に、いろいろ調整しても治らなかったのに再起動したら改善したということもまぁよくある(正直良いノウハウではないが)。
しかし、再起動時のあれこれでデータが損壊する可能性も否定できない。

### ワンチャンあるんじゃね
30分ほど悩んだものの、結局電源長押ししてみた。
そしたら普通に OS が上がってきた。
![hdd_error.png](https://qiita-image-store.s3.amazonaws.com/0/71497/55b43812-7873-0c7d-765d-b439eeb421c5.png "hdd_error.png")
喜んでいるのもつかの間、エラーが出ているようだ。
読んでみると、以下のどっちかを行えと書いてある。

* ルートでログインして fsck しろ
* Control 押しながら D を押せ

とりあえず `Control + D` を試してみたところ、再起動してまたこの画面に戻ってきた。

### おとなしく fsck しましょうか
ルートパスワードを入力しログイン。
入力待ちになってるので `fsck` を入力し Enter を押すと、何やら作業が始まった。
しばらく待っているとディスクチェックと修復が行われる。
ときどき `Fix<y>?` と出てくるので Enter で応答してやると次々と修復が進む。
![hdd_fix.png](https://qiita-image-store.s3.amazonaws.com/0/71497/d0b2814d-f621-a9ad-841f-31cab607d1bf.png "hdd_fix.png")
リブートしろと書いてあるので、`Control + ALT + DELETE` で容赦なく再起動する。

## 元気に走り回る CentOS5.8 ちゃんの姿が
ということで、 **今回は** これで無事サーバが復旧した。
必ずしもこれで治るわけじゃないし、今回もこの後いろいろ検証しなければならないし、とりあえずバックアップの取得はした方が良い。

今回のサーバは HDD の容量が 25GB という化石のようなマシンだったので、張り付いて Enter 叩くマンで良かったし、作業時間も1時間かからない程度だった。
しかし、今時のサーバだと恐ろしいことになることは想像に難くないので、 `fsck -y` とした方がいいと思う。
【超丁寧】Rails4.2 + AWS + nginx でウェブアプリのproductionを http → https に移行させた方法

#イントロ
railsのウェブアプリが既にAWSのEC2インスタンスで稼働しており、ドメインも取得済みの状態を前提にしています。
rails:4.2.0
nginx: 1.10.2


#Rails側の準備
以下のコードを追加します。

```/etc/nginx/nginx.conf
#nginxのconfigファイル

#httpでアクセスされたものをhttpsにリダイレクト
server {
        listen 80;
        proxy_set_header X-Forwarded-Proto $scheme;
        if ( $http_x_forwarded_proto != 'https' ) {
          return 301 https://$host$request_uri;
        } 

#httpsサーバー
server {
        listen 443 ssl;
        server_name ウェブサイトurl;
    }
```

```/your/rails/app/config/environments/production.rb
#コメントアウトされていたものを外す
#全てのアクセスをhttpsに強制する
config.force_ssl = true
```

#AWS側の準備

##1. Amazon Certificate ManagerでSSL証明書を取得する

こちらのサイトの「利用手順」→「証明書の作成」に従って証明書を作成してください。すぐ終わります。

##2. ELBでClassic Load Balancerの作成

EC2→Load Balancers→Create a Load Balancerでロードバランサーを作成します。

###Select Load Balancer Type
Classic Load Balancer を選択。

###Step 1: Define Load Balancer
適当な名前を決めて、プロトコルを１つ追加（画像参照）。その他はデフォルトのままでいい。

![スクリーンショット 2017-05-24 19.46.09.png](https://qiita-image-store.s3.amazonaws.com/0/164818/034d74c8-af68-683e-7590-948b3997f4c9.png)

###Step 2: Assign Security Groups
新しいsecurity groupを作成、その他はデフォルトのまま。下の画像のようになるはず。![スクリーンショット 2017-05-24 19.47.33.png](https://qiita-image-store.s3.amazonaws.com/0/164818/16638c5f-91cb-0911-c633-112482a0ccdd.png)

###Step 3: Configure Security Settings
先ほど作成したcertificateを選択。その他はデフォルトのまま。

###Step 4: Configure Health Check
ping protocol : TCP, ping port : 80 に変更。その他はデフォルトのまま。

###Step 5: Add EC2 Instances
ウェブアプリのEC2インスタンスを選択。

###Step 6: Add Tags
特に必要なし

###Step 7: Review
設定を確認して完了。

##3. Route53の設定

Route53に登録されている自分のドメインのAレコードのALIASをLoadBalancerのDNS名に変更。
![スクリーンショット 2017-05-24 19.55.17.png](https://qiita-image-store.s3.amazonaws.com/0/164818/762520cb-d9af-fa8a-f39b-07c5f2348f41.png)

これで設定は全て終了！httpsからアクセスできるようになっているはずです。

##参考にしたサイト・記事

AWSでドメイン、SSL証明書の取得、設定
http://qiita.com/masch/items/a5ef84998fb7784f9115

AWS ELB, Nginx, Rails, SSL: The final word.
http://pricees.github.io/2014/03/25/aws-elb-nginx-rails-ssl-the-final-word/

AWS Certificate ManagerでSSLをお手軽に！
http://blog.serverworks.co.jp/tech/2016/04/07/acm_beginner/

##最後に
筆者はまだエンジニア経験が浅く、理解も十分でない点もあるので間違いや改善点があればぜひご指摘お願いします。
SQLiteからMySQLへのデータ移行

[17/6/1] 改行コード(char(10)/char(13))を含むデータに対応できるよう修正

WebアプリのバックエンドをSQLiteからMySQLに移行するための備忘録です。

SQLiteでダンプしたものを何も考えずにMySQLに突っ込むとFOREIGN KEYなどの制約が抜けてしまう状況だったので、migrationはアプリ付属の初期化スクリプトを使い、データだけをSQLiteから移行するという方針です。

```text:動作環境
sh: FreeBSD 11の/bin/sh
sqlite3: 3.18.0
MySQL: 5.6
```

## データ抽出スクリプト
SQLiteのDBからMySQL投入用のSQLを生成するスクリプトです。こちらは[stack overflow](https://stackoverflow.com/questions/4199850/sqlite-export-with-column-names)から拝借してきたものを少し修正しました。
元のスクリプトの

- '\nINSERT INTO table'という文字列を含むデータがあると上手くいかない

という制約は残っていますが、

- カラム名に特殊な文字があるとダメ

という制約の方は対策してあります。


```sh:sqlite2mysql.sh
#!/bin/sh

SQLITE=sqlite3

if  [ -z "$1" ] ; then
        echo usage: $0  sqlite3.db
        exit
fi

DB="$1"

TABLES=$("$SQLITE" "$DB" .tables)
#echo "-- $TABLES" 
echo 'BEGIN;'
echo 'SET FOREIGN_KEY_CHECKS = 0;'

for TABLE in $TABLES ; do
        echo 
        echo "-- $TABLE:";
        echo "TRUNCATE TABLE $TABLE;"
        COLS=$("$SQLITE" "$DB" "pragma table_info($TABLE)" |
          cut -d'|' -f2 )
        COLS_CS=$(echo $COLS | sed 's/ /","/g')
        COLS_CS2=$(echo $COLS | sed 's/ /`,`/g')

        echo -e ".mode insert\nselect \"$COLS_CS\" from $TABLE;\n" |
          "$SQLITE" "$DB" |
          sed "s/^INSERT INTO \"table\"/INSERT INTO $TABLE (\`$COLS_CS2\`)/" |
          sed "s/'||//g" | sed "s/||'//g" | sed 's/char(13)|\{0,2\}/\\r/g' | sed 's/char(10)|\{0,2\}/\\n/g'
done
echo 'SET FOREIGN_KEY_CHECKS = 1;'
echo 'COMMIT;';
```

## データ抽出

例として、[Roundcube](https://roundcube.net/)のデータの移行手順を記述します [^1]。

[^1]: これが目的だったんですが(^^;

```text:データ抽出
% sh sqlite2mysql.sh roundcube.db > rc_data.sql
```
で、rc_data.sqlの内容は以下のようになります。

>```text:rc_data.sql
BEGIN;
SET FOREIGN_KEY_CHECKS = 0;
-- cache:
TRUNCATE TABLE cache;
-- contactgroupmembers:
TRUNCATE TABLE contactgroupmembers;
INSERT INTO contactgroupmembers (`contactgroup_id`,`contact_id`,`created`) VALUES(1,10,'2017-05-24 07:00:00');
 :
INSERT INTO identities (`identity_id`,`user_id`,`changed`,`del`,`standard`,`name`,`organization`,`email`,`reply-to`,`bcc`,`signature`,`html_signature`) VALUES(...);
SET FOREIGN_KEY_CHECKS = 1;
COMMIT;
```

## データ投入

出来上がったrc_data.sqlをMySQLに投入します。[DB名]のデータベースの初期化は済ませてあるものとします。

```text:データ投入
% mysql -u [DBユーザ] -p [DB名] < rc_data.sql
```
途中でエラーが出たらロールバックするので、1行ずつコツコツと修正します。

各テーブルのINSERT直前にTRUNCATEしているので、やり直しもできます。

以上。
プルリクエストを出してレビューしてもらった時に指摘されたことメモ

GitHubを使い始めて2週間目です。
プルリクエストを出してレビューしてもらう際に同じことを二度と言われないようにするべく、レビュー時に指摘されたことを逐一書き足して行きます。

経験豊富な方から見て、「これも気をつけるべし」というのがあればバシバシご指摘ください。


# 指摘されたことメモ

- 不要なファイルは消す
- 余分な空行は消す(式中も、最下部も)
- ルーティングにresourcesを使う場合は不要なものは省く
- ビューを変更した際はスクショを貼り付ける
- GET '○○/○○'　よりは、プレフィックスで指定した方が良い(redirect設定時)
- デバッグ時の記述は消す(binding.pryとか)(作業の難易度が高いほど、見直しを忘れがちになるので注意)


今後も随時書き足して行きます。
Swift3で日付（Date）の比較が超簡単になっていた件

これまで日付、Dateの比較ってすごく面倒だし、わかりにくかったです。

```Swift:Swift
let today : Date = Date()
let yesterday: Date = Date(timeIntervalSinceNow:-60*60*24)

if today.compare(yesterday) == ComparisonResult.orderedDescending {
   print("今日は昨日よりも未来")  // 実行される
}
```

正直、``orderedDescending``とか``orderedAscending``ってどっちがどっちだっけ…といつも迷っていました。

ですが、Swift3から新しく追加された``Date``型であれば、比較演算子で比較ができるのです。
本当に嬉しい。

```Swift:Swift
let now : Date = Date()
let yesterday: Date = Date(timeIntervalSinceNow: -60*60*24)
let tomorrow: Date = Date(timeIntervalSinceNow: 60*60*24)
let anotherNow : Date = Date()
let otherNow : Date = now

if tomorrow > now {
   print("tomorrowはnowよりも未来")  // 実行される
}
if tomorrow != now {
   print("tomorrowとnowは違う日")  // 実行される
}
if yesterday > now {
   print("yesterdayはnowよりも未来")  // 実行されない
}
if yesterday < now {
   print("yesterdayはnowよりも過去")  // 実行される
}
if now == anotherNow {
   print("nowとanotherNowは同じ")  // 実行されない
}
if now == otherNow {
   print("nowとotherNowは同じ")  // 実行される
}
if now <= anotherNow {
   print("nowはanotherNowよりもちょっとだけ未来")  // 実行される
}
```

上記で``now``と``anotherNow``は同じように見えますが、``anotherNow``が``now``よりも後に実行されています。
この数行のコード間の数ミクロン秒の差があるので、``now``と``anotherNow``は同じではないということですね。

あぁ、嬉しい。
（今更かよ！って思われるかもしれませんが、、、）
問題: 月額課金の開始日が与えられたとき，今日の日付をもとに次回の決済日を算出せよ

# 問題

月額課金の開始日が与えられたとき，今日の日付をもとに次回の決済日を算出せよ。

- 言語はPHPを推奨する。 <font color="silver">(今僕がPHPの業務でこのコード書きたくて困ってるから)</font>
- 日付に伴う時刻はすべて `00:00:00` とする。
- **決済日が今日である場合，来月の決済日を算出する。**
- **「月」に`+1`しただけでは「日」が未定義になる場合，その月の最終日を採用する。**<br>例: `2016-03-30`が課金開始日で今日が`2017-01-31`の場合，次回決済日は`2017-02-28`


# 関数シグネチャとテストケース

```php:PHP
<?php

use DateTimeImmutable as DTI;

/**
 * @param DTI $recursionBaseDate 月額課金の開始日
 * @param DTI $today 今日
 * @return DTI 次回の決済日
 */
function getNextPaymentDate(DTI $recursionBaseDate, DTI $today): DTI
{
    // ここに実装
}

// 基本的なケース
assert(getNextPaymentDate(new DTI('2016-01-05'), new DTI('2017-12-31')) == new DTI('2018-01-05'));
assert(getNextPaymentDate(new DTI('2016-01-05'), new DTI('2017-01-04')) == new DTI('2017-01-05'));
assert(getNextPaymentDate(new DTI('2016-01-05'), new DTI('2017-01-05')) == new DTI('2017-02-05'));

// 開始日が未来のケース
assert(getNextPaymentDate(new DTI('2017-03-31'), new DTI('2017-01-30')) == new DTI('2017-03-31'));

// 単純計算だと日付が未定義になるケース
assert(getNextPaymentDate(new DTI('2015-01-30'), new DTI('2016-01-31')) == new DTI('2016-02-29'));
assert(getNextPaymentDate(new DTI('2015-01-30'), new DTI('2017-01-31')) == new DTI('2017-02-28'));
assert(getNextPaymentDate(new DTI('2015-01-30'), new DTI('2016-02-01')) == new DTI('2016-02-29'));
assert(getNextPaymentDate(new DTI('2015-01-30'), new DTI('2017-02-01')) == new DTI('2017-02-28'));
```

# 解答

前者の改善案のほうがわかりやすくておすすめ

```php:@ngyuki案
function getNextPaymentDate(DTI $recursionBaseDate, DTI $today): DTI
{
    // 決済開始日が未来の場合はその日を返す
    if ($today < $recursionBaseDate) {
        return $recursionBaseDate;
    }

    // 決済開始日の日付
    $d = (int)$recursionBaseDate->format('d');

    // 今日の年月
    $y = (int)$today->format('Y');
    $m = (int)$today->format('m');

    // 「今日の日」が「決済開始日の日」以降なら翌月
    if ((int)$today->format('d') >= $d) {
        $m++;
        if ($m > 12) {
            $m = 1;
            $y++;
        }
    }

    // 決済日の月の日数を求める
    $days = (int)(new DateTimeImmutable())->setDate($y, $m, 1)->format('t');

    // 決済日の日が月の日数を超えているなら月の最終日
    if ($d > $days) {
        $d = $days;
    }

    return (new DateTimeImmutable())->setTime(0, 0, 0)->setDate($y, $m, $d);
}
```

```php:@mpyw案
function getNextPaymentDate(DTI $recursionBaseDate, DTI $today): DTI
{
    // 決済開始日が未来の場合はその日を返す
    if ($today < $recursionBaseDate) {
        return $recursionBaseDate;
    }

    // 「今月の決済開始日と同じ日」を求める，但し月がズレてしまったら日が足りないと見なして今月の最終日を採用する
    $same = $today->setDate($today->format('Y'), $today->format('m'), $recursionBaseDate->format('d'));
    if ($same->format('Y-m') !== $today->format('Y-m')) {
        $same = $today->modify('last day of');
    }

    // 「今月の決済開始日と同じ日」がまだ過ぎていなければそれを返す
    if ($today < $same) {
        return $same;
    }

    // 「今月の決済開始日と同じ日」の1ヶ月後と，次の月の最終日を求める
    $next1 = $same->modify('next month');
    $next2 = $same->modify('last day of next month');

    // 次の月をスルーしていたら日が足りないと見なして次の月の最終日を返し，そうでなければ計算上の1ヶ月後を返す
    return $next1->format('Y-m') === $next2->format('Y-m') ? $next1 : $next2;
}
```

誤りや改善案があればコメント欄にて
CircleCI2.0でDockerImageを使う

## CircleCIのビルドが遅い問題
 [codenize-tools](https://codenize.tools/)を利用して、AWSまわりの設定をリポジトリで管理しているが、
設定のチェック、デプロイに時間がかかっていた。

 => 2.0のDocker対応で解決しよう!!

## CustomImageを作ってみる
CircleCIはCustomのDockerImageをサポートしています。
[saorio/codenize_tools_circleci](https://hub.docker.com/r/saorio/codenize_tools_circleci/tags/)ような、DockerImageを作ります。

内容としては、
　- [circleCIの公式イメージ](https://hub.docker.com/r/circleci/ruby/tags/)　※ここではruby2.2系を使用。
　- codenize-toolsのgem一式をインストール

```Dockefile:Dockerfile
FROM circleci/ruby:2.2.7
WORKDIR /root/
ADD work work

COPY work/Gemfile $WORKDIR

RUN sudo apt-get update && sudo apt-get upgrade -y
RUN sudo apt-get install -y libpcap-dev

WORKDIR /root/work/
RUN sudo bundle install
```

CircleCI公式を使った方が、よく使われるライブラリなどが入っててOSの公式を使うよりDockerfileがシンプルになって良いのでこちらを利用しています。

これをpullしてきて使うcircle.ymlを書く。

```yaml:circle.yml
version: 2
jobs:
  build:
    docker:
      - image: saorio/codenize_tools_circleci:latest
    working_directory: ~/<your-repository-name>
    environment:
      AWS_REGION: us-east-1
    steps:
      - checkout
      - run:
          name: miam dry-run
          command: |
            miam --dry-run --apply -f IAMfile --region ${AWS_REGION} --no-color --no-progress
      - deploy:
          name: miam deploy
          command: |
            if [ "${CIRCLE_BRANCH}" == "master" ]; then
              miam --apply -f IAMfile --region ${AWS_REGION} --no-color --no-progress
            fi
```
そのままAWSにdeployするなら `--dry-run` を外してdeploy可能。
長い時で3分くらいかかっていたのが10秒程度になりました :smiley: 

![pasted_image_at_2017_05_25_01_56_pm.png](https://qiita-image-store.s3.amazonaws.com/0/100546/543e4605-dbf1-52c0-da4d-c32f866a2fe9.png)
↓
![pasted_image_at_2017_05_25_01_57_pm.png](https://qiita-image-store.s3.amazonaws.com/0/100546/fd26d6e0-75d6-0a51-fac3-ae70517ceca5.png)
【laravel】マイグレーションファイル作成時にmodelも一緒に作る

毎回コマンドを探すのでメモ(正確には、モデル作成時にマイグレーションファイルも作成なんでしょうが)

意外と検索するとマイグレーションファイルだけ、modelファイルだけ
の作成方法しか出てこないが、名前付けるのミスりやすいので一緒に作りたい

```
php artisan make:model TempTable --migration
```

これだけなんですが、探すと出てこないもので

※参考
https://readouble.com/laravel/5.4/ja/eloquent.html
Fatal error: Uncaught Error: Class 'Illuminate\Foundation\Application' not found 

```
Fatal error: Uncaught Error: Class 'Illuminate\Foundation\Application' not found in /Users/UserName/PhpstormProjects/laravelApp/bootstrap/app.php:14
```

試した、ダメ
``$ git clone composer install``

試した、ダメ
``$ git clone composer update``

ググる・・・

``$ composer update --no-scripts``

参考サイト
https://laracasts.com/discuss/channels/general-discussion/fatal-error-class-illuminatefoundationapplication-not-found-in-pathtoprojectbootstrapappphp-on-line-14?page=1
create-react-app-typescript で出来た Jest 単体テストのデバッグ



create-react-app-typescript で作ったアプリの単体テスト (Jest) のデバッグを VSCode 上で行おうとして失敗した。
どうしても必要な時に最低限使えるよう SourceMap が無効になったデバッグには成功したので記録に残す。

* 出来ること
    * Chromium の DevTool を使って変数参照を行う。
    * debugger; を仕込んで途中でブレイクする。
* 出来ないこと
    * TypeScript のソースコードを表示すること。(トランスパイル結果しか見えない)

プロジェクトで以下を実行 5858 はよく使われるポートらしい。

    $ CI=true node --debug-brk node_modules/react-scripts-ts/scripts/test.js --env=jsdom --runInBand
    Debugger listening on [::]:5858

* node のオプションの意味
    * --debug-brk : デバッグ開始時停止する。その間にブラウザを接続したり出来る。
* Jest のオプションの意味
    * --env=jsdom : DOM を用意する。
    * --runInBand : 直列に実行する。デフォルトでは複数プロセスで動くのでテスト出来ない。

.vscode/launch.json の設定 (歯車ボタン > 画面右下の Add Configuration... > Node.js : Attach to Process で出来る)

      {
        "type": "node",
        "request": "attach",
        "name": "Attach to Process",
        "processId": "${command:PickProcess}",
        "port": 5858
      },
    
* 再生ボタン > "Attach to Process" を選ぶと vscode はポート番号 5858 でデバッグを開始する。
* TypeScript のソースコードを見れないので、ブレイクポイントの設定には debugger; 文を使う。

yarn run eject したり色々試してみたが駄目だった。
GaurunでのGCM(FCM)とAPNsの設定方法

GaurunのGCMとAPNsの設定に苦戦したのでメモ。

【動作環境】
Ubuntu14.04
Gaurun 0.8.1

## GCM(FCM)のAPI Keyを発行する
FirebaseからAPIキーを発行する。
<https://firebase.google.com/docs/cloud-messaging/server?hl=ja#http-->

上記ページにも記載されているが、
APIキーが正しいものかを確認するには下記コマンドを実行する。
401エラーが出なければOK。

```
api_key=YOUR_SERVER_KEY

curl --header "Authorization: key=$api_key" \
       --header Content-Type:"application/json" \
       https://fcm.googleapis.com/fcm/send \
       -d "{\"registration_ids\":[\"ABC\"]}"
```


## APNsの証明書と鍵を発行する
APNs Provider APIを使用する。
<https://developer.apple.com/jp/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html#//apple_ref/doc/uid/TP40008194-CH101-SW>1

証明書と鍵の発行は下記サイトを確認する
<https://developer.apple.com/jp/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW11>

p12ファイルを入手したら下記コマンドを実行し、証明書と鍵ファイルを生成する。

```
openssl pkcs12 -clcerts -nokeys -out hoge_cert.pem -in hoge.p12
openssl pkcs12 -nocerts -out hoge_key.pem -in hoge.p12
```

この証明書が正しいかどうかは下記コマンドで確認できる。
エラーが出なければOK。

```
# 開発環境
sudo openssl s_client -connect api.development.push.apple.com:443 -cert hoge_cert.pem -key hoge_key.pem

# 実稼働環境
sudo openssl s_client -connect api.push.apple.com:443 -cert hoge_cert.pem -key hoge_key.pem
```

## Gaurunの設定
gaurun.tomlに設定する内容を記載する。
GCMおよびAPNsに関するもののみ抜粋。

```
[android]
enabled = true
apikey = "上記で生成したGCM(FCM)のキー"
use_fcm = true # 今回はFCMを使用したのでtrue

[ios]
enabled = true
pem_cert_path = "上記で生成したcertファイルのパス"
pem_key_path = "上記で生成したkeyファイルのパス"
sandbox = true # 開発環境用の証明書の場合、true
topic = "バンドルID"
```
オフラインリアルタイムどう書くF05の問題


オフラインでリアルタイムに「どう書く」をやるイベント( https://yhpg.doorkeeper.jp/events/60171 )を行っています。

問題は「ブロックを回す」という名前で、詳細は
http://nabetani.sakura.ne.jp/hena/ordf05rotblo/
です。

出題者の気分としては、問題を読み始めてから解けるまで30分あればなんとかなると思ってますが、ひとそれぞれで。

実装ができた方はこちらのコメント欄からリンクを張っていただくと見つけやすくて助かります。

似たような問題をもっと解きたいという方は、
https://nabetani.hatenadiary.com/entry/yhpg_list
に過去問リンク集がありますので、そちらをご覧になると良いと思います。
PHP Toolboxプラグインを使ってPhpStormでモッキングを快適に

## イライラ

素の PhpStorm でイラっとくる箇所といえばダントツ、PHPUnit のモックあたりですよね。こう書かないといけないの。

```php
$connector = new SomeMiddlewareProcess();

/** @var MiddlewareInterface|\PHPUnit_Framework_MockObject_MockObject $processor */
$processor = $this->createMock(MiddlewareInterface::class);
$connector->setProcessor($processor);
```

`setProcessor` の引数定義に MiddlewareInterface のタイプヒント付いてて、docコメントがないと MockObject 型だぜ間違ってるYo! って警告にされちゃうやつ。

最近だと `assert(... instanceof ...)` でもOKになってますが、これもなぁ... 他人に与えられた値でもないのにアサーションってどうよっていう。

```php
$processor = $this->createMock(MiddlewareInterface::class);
assert($processor instanceof MiddlewareInterface);
$connector->setProcessor($processor);
```

なんか負けた気がするやつがこれ。テストコードが、それに対応する自動テストなしに高級化していく、という闇の前兆を感じます。

```php
/**
 * @return MiddlewareInterface
 */
private function createMiddlewareInterfaceMock()
{
    return $this->createMock(MiddlewareInterface::class)
    // ->method(...)->will...
    ;
}
```

## スッキリ

PHP Toolbox を導入します。

<img width="936" alt="スクリーンショット 2017-05-24 17.31.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/11525/bcd85c11-96eb-fd94-55b6-b3981fd949a7.png">

設定を確認します。

<img width="1052" alt="スクリーンショット 2017-05-24 17.00.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/11525/72e7f5d5-8102-fdab-7cb8-e99ff6b7bfbd.png">

Open で設定保存場所を開きます。

[idea-php-toolbox-json-files](https://github.com/Haehnchen/idea-php-toolbox-json-files) をここにダウンロード。

```
~/Library/Preferences/PhpStorm2017.1$ git clone \
git@github.com:Haehnchen/idea-php-toolbox-json-files.git \
php-toolbox/vendor/php-toolbox
```

`vendor/php-toolbox` に入れたのは、他の提供者がいたときと、自分が手でカスタマイズしたいときのため。

```
~/Library/Preferences/PhpStorm2017.1
└── php-toolbox
    └── vendor
        └── php-toolbox
            ├── behat
            ├── core
            ├── doctrine
            ├── http
            ├── mockery
            ├── php-http
            ├── phpunit  <--- これのおかげ
            ├── psr
            ├── symfony
            ├── twig
            └── zend
```

やっぽい!

<img width="751" alt="スクリーンショット 2017-05-24 17.58.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/11525/36374913-157b-b9a7-d631-d6561ed251cd.png">

`createMock()` の戻り値が勝手に、型指定 doc コメント付けたみたいになりました。

他にもいろいろおまけ付き!

<img width="542" alt="スクリーンショット 2017-05-24 18.10.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/11525/ea0e1bf0-211e-b45e-4898-e71a3fbdfe4c.png">

がんばったら JSON を書くだけでオレオレフレームワークのマジカルな部分に、独自の補完サポートを付けられるかもですよ。