OmniAICreator/Qiita-1.07M huggingface dataset:
サーバーサイドエンジニアになってわからなかったこと(4週間目)

# お勉強の経緯
- 最近転職しました。
- 転職前はSESでミドルソフトを作ってました。
- Webに関わる仕事はやったことはない。
- PHPとPythonとJavaScript、C・C++がﾁｮｯﾄﾜｶﾙ。

# 勉強したこと

- ログ収集→**fluentd**なるものでできるらしい
- データの可視化→**ElasticSearch + Kibana**ってのでできるらしい

# ログ収集

## fluentd

ログを集めるツール。
特にサーバ10台とか20台とかのログを集めるのに使う感じです。
特にLBとかで分散処理をした場合は、同じユーザのログが違うサーバに保存されたりするので、それをうまくまとめるえらい子らしいです。

- APサーバに入れて、ログ集約サーバやAWSのS3に送ったりする
- ログ集約サーバに入れて複数のログファイルを統合、またほかのサーバやS3におくる

とかで使うらしい。送る方にも送られる方にも入れるものなんですねーー

### つまづきぽいんと

Amazon Linux2で環境構築してました。

```bash:install_fluentd.sh
# とりあえずyumはupdateしとこう
sudo yum -y update

# fluentd入れたいというお気持ち
sudo yum install fluentd
# ないって言われる
```
公式のドキュメントをを見ましょう。ちゃんと書いてある。 Amazon Linux2はRedHat系なので

```bash:install_fluentd.sh
curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.5.sh | sh
```


あとPermission関係とかは設定ファイルで実行者をrootにするとうまくいくよ


# データの可視化

## ElasticSearch

インストールは公式を見ろ（N回目）Java8を忘れちゃだめだぞ！！！

```bash:install_ElasticSearch.sh
# とりあえずyumはupdateしとこう
sudo yum -y update

# yumにレポジトリ？を追加するの
sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch
# 設定に追記？(内容は公式見てね)
sudo vim /etc/zypp/repos.d/elasticsearch.repo
# いんすとーーる
sudo yum install elasticsearch
```

公式さんをみると大体できる。


あと、稼働状況はちゃんと確認しましょうね

```bash:test.sh
systemctl status elasticsearch
```

あと設定ファイルはちゃんと見ましょうね。ポート開けとか

## kibana 

公式をみるのだ。。。。
ちゃんとやり方は書いてある・・・

ポートとホストの設定は忘れずに。

ポートが開いてるかは↓で確認するとよさげ？？

```bash:port_check.sh
netstat -au
```

# 最後に

ちょっとずつ追記します。
php-master-changes 2018-11-06

今日は C++ コードで zend_string_equal_val() を参照しようとしたときのビルドエラー修正、Mac でのビルド問題の修正、libmagic のコードの微修正とパッチの更新、ドキュメントの更新、opcache のびみょーな最適化があった！

# 2018-11-06
## remicollet: Fix: [#77110](https://bugs.php.net/bug.php?id=77110) undefined symbol zend_string_equal_val in C++ build
- https://github.com/php/php-src/commit/d53ecd040bc03ff1504e0fa74fd675df336f9451
- C++ コードで Zend/zend_string.h から zend_string_equal_val() を参照しようとすると未定義シンボルとしてエラーになる問題の修正
- remi さんが swoole 使う時に[気付いた](https://github.com/swoole/swoole-src/issues/2089)もののもよう

## remicollet: NEWS
- https://github.com/php/php-src/commit/d78479737c8a078fccf57c3f1f21ef3104430cba
- [7.3~]
- ↑の NEWS への追記

## cmb69: Fix [#76825](https://bugs.php.net/bug.php?id=76825): Undefined symbols ___cpuid_count
- https://github.com/php/php-src/commit/7625f972db10fe1a69757b97c6dec57ea049129b
- [7.3~]
- Mac の Xcode に付いてくる clang や gcc を使う際、そのバージョンの問題で ___cpuid_count が見つからずビルドに失敗する問題の修正
- ___cpuid_count の有無の判定を autoconf で実際にリンクできるか試して行うようにした

## weltling: Declare function proto in header
- https://github.com/php/php-src/commit/29dcf19f8b40dff2183c415188228f725547b1bb
- [7.3~]
- ext/fileinfo で libmagic のコードにあった関数 convert_libmagic_pattern() の宣言をヘッダへ移動

## weltling: Update libmagic.patch [ci skip]
- https://github.com/php/php-src/commit/a957af6c0622a473dcb44f2193b6a38195437edb
- [7.3~]
- ext/fileinfo で libmagic へのパッチを更新
- [一昨日](https://qiita.com/sj-i/items/a4dc7faf53c94024309e#weltling-rework-places-in-libmagic-regarding-previous-cve-2014-3538-fixes)と[昨日](https://qiita.com/sj-i/items/6e58bc3f83e06ba84e2f#weltling-backport-7f5f4601-for-72)と[今日](#weltling-declare-function-proto-in-header)で入れていた修正のパッチへの取り込みみたいな感じ

## weltling: Update NEWS [ci skip]
- https://github.com/php/php-src/commit/ddd54401db16da197c0ffb7be613e0f90aab8872
- [7.3~]
- ext/fileinfo で libmagic の修正により [#77095](https://bugs.php.net/bug.php?id=77095) が解決したことを NEWS へ追記

## cmb69: [ci skip] Update NEWS wrt. php-7.3.0RC5 tagging
- https://github.com/php/php-src/commit/155aecd397d09fb97aea7b3c3eb8a91e1d5dacb0
- [7.3~]
- php-7.3.0RC5 のタグを打って 7.3 系の開発バージョンを PHP 7.3.0RC6 へ移行したことを NEWS へ反映

## dstogov: Micro-optimization
- https://github.com/php/php-src/commit/bfaf662ac2e58c16208224f32cb8387a35b3da97
- ext/opcache の比較的みみっちい最適化
[Node.js][lodash] オブジェクトの配列をユニークにする（マージする）

オブジェクトの配列をユニークする（マージする）方法です。結果は配列のオブジェクトになります。
null は値としてカウントせず、 null 以外の値が重複した場合だけユニークにしています。

```js
const lodash = require('lodash');

let array = [
  {
    "job": "会社員",
    "name": "荒木　幸也"
  },
  {
    "job": "自営業",
    "name": "森岡　七美"
  },
  {
    "job": "会社員",
    "name": null
  }
];

let result = array.reduce(function(res, obj){
  Object.keys(obj).forEach(function(k){
    res[k] = res[k] || [];
    res[k] = res[k].concat(obj[k]);
    res[k] = lodash(res[k]).uniq().compact().value();
 });
 return res;
},{});
/*
 => {
   "job": [
     "会社員",
     "自営業"
   ],
   "name": [
     "荒木　幸也",
     "森岡　七美"
   ]
}
 */
```
Ansibleでcsvからパスワード取得

# Ansibleでcsvからパスワード取得
パスワードのようなバージョン管理したくない情報を、別途csvに記述してアクセスする。

# lookupプラグイン
Ansibleから、ローカルにあるファイルを参照することができる。
`lookup()`の第1引数にはプラグイン名を指定する。csvファイルを指定する場合は、`csvfile`。
第2引数では、探し出すkeynameとパラメータを指定する。

#### パラメータ
* file : ファイル名
* delimiter : 区切り文字（デフォルトでは、タブになっている）
* col : 取り出す列（1番左を0としてデフォルトでは、1になっている）

```csv:password.csv
name,password
hoge,passhoge
geho,passgeho
piyo,passpiyo
```
```yml:ユーザ追加
- name: ユーザ作成
  become: True
  user:
    name: "{{ item }}"
    password: "{{ lookup('csvfile', item + ' file=password.csv delimiter=,') }}"
  with_items:
    - hoge
    - geho
    - piyo
```

[Lookup Plugins — Ansible Documentation](https://docs.ansible.com/ansible/2.5/plugins/lookup.html)
[csvfile - read data from a TSV or CSV file — Ansible Documentation](https://docs.ansible.com/ansible/2.5/plugins/lookup/csvfile.html)
MySQLの特徴的なこと

2018年11月10日追記
タイトルとタグを変更しました。
最初はgroup byについてのみ記載するつもりでしたが下記のお仕事をしていく中で他にも知らなかったMySQL独特の文法・特徴があるのを知りました。
それらに悩まされることが増えたのでそれについても下に追記していきます。
基本私が仕事でなんじゃこりゃとなったものを記載していく予定なので差異を網羅するような内容にはなっていません。
またgroup byについてだけ詳しく書いてますが消したりはしないでおこうと思います。

#はじめに
私は現在仕事でMySQLで手バッチ実行するシステム？？？？の刷新をしています。
AbinitioというBIツールを使っています。
その中でちょっと驚いた事があったので備忘も兼ねて投稿します。
そんなの当たり前じゃんって言わないでね。

##どんなお仕事をしているか？
MySQL上のデータ（だいたい数百万件とかそんくらい）をAbinitioってBIツールを使って自動化、高速化するお仕事です。
それにあたり現在動いているSQLをツール上に取り込む必要があります。
ある一定レベルは自動でやってくれるんですがこのツールはANSI対応のものしか組み込まれていません。
そのためMySQLの独自の関数、仕様的なものは都度対応していかないといけないといった感じです。

#group byについて
SQLでレコードを集約して取得する方法です。
例えば
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137987/99eb793c-cb29-b273-455f-0fab1ae663b2.png)
こんなテーブル１があって
select カラム１、カラム２　
form　テーブル１　
group by カラム１、カラム２
というSQLを投げた場合
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137987/d5c45e54-c1f8-ff1d-38d7-b4f8235fc6c0.png)
こんな感じでデータが取れます。
（１と２のレコードが集約される）
ここで大切なのはselectのあとで取得しているカラムとgroup byのあとで指定している項目は同じものを指定しないといけないことです。
group byで指定せずselectで取得できるのはsumやcount関数を使用した項目になります。
ここで私が驚いたことですがMySQLでは上記のルールを守らなくていいらしいです。
なので通常ではエラーになる
select カラム１、カラム２　
form　テーブル１　
group by カラム１
こんなのも実行できます。
ちなみにその時テーブルが
![image.png](https://qiita-image-store.s3.amazonaws.com/0/137987/ca041e58-1b6b-fe19-7685-96d1a71ce3a9.png)
こんな形だった場合、２と３のレコードは集約されるわけですがカラム２が違うのでどちらが表示されるかわからないらしいです。
（基本上にある２のほうが表示されるようですが）
[MySQL での GROUP BY の処理](https://dev.mysql.com/doc/refman/5.6/ja/group-by-handling.html)
こちらにも記載がありますが
>この機能を使用すると、不要なカラムのソートおよびグループ化が回避されるため、パフォーマンスを改善できます。
>ただし、これは主に、GROUP BY で名前が指定されていない各非集約カラム内のすべての値がグループごとに同じである場合に役立ちます。
ということで１つ目みたいなテーブルだとわざわざ２つ指定しなくていいから有効だけど２つ目みたいなテーブルでは良くないよってことみたいです。

#insert文のカラム指定（以下2018年11月10日追記）
上記のgroup byのような話がinsert時もあるようです。
具体的に説明すると上記で説明したカラムが2つあるテーブルに対して
insert カラム１ value（A）;
みたいなSQLを実行した場合、カラム２の設定がないためエラーが発生します。
ただMySQLの場合、特にエラーなく実行されカラム２にはデフォルト値として設定した値が入るようです。

#ignore
エラーを無視する魔法の呪文（）
例えば登録処理をするときなどPKエラーが発生するような内容だとその旨エラーが発生します。
そのエラーを無視して次のSQLの実行等を行うというもの（エラー自体が発生してないように見える）
データの登録自体は行いません。
連続してSQLを実行して途中で止まると困るみたいな場合や一旦selectかけて調べるのめんどくさいみたいな場合に使うんだと思われますがあまりよくない（っていうか使ってほしくない）と思います。

#命名ルール
Oracleなど（私が今使ってるツールも）カラム、テーブルの名前に先頭は数字が使えません。
MySQLだと使えるようです。
仕事でもバンバン出てくるので置換してます・・・

#NULLの扱い
MySQL（PostgreSQLでも）NULLと空文字を区別しましす。
またその区別をつけるためかcsvとしてexportするとデータにNULLとして入ったりします。
このデータを取り込むとNULLを文字列として認識するので全部エラーになっています・・・

#DUAL表
日付などの演算を行うとき仮のテーブルとしてOracleではDUAL表の指定を行います。
PostgreSQLではDUALという概念がないようです。
MySQLではどちらでも実行できるようです。

#組み込み関数について
これはMySQLに限らず結構差異がある感じです。
止むえない部分ですが関数名が同じだけど引数が違うとかだと結構ややこしくなってきますね。

#型定義について
OracleとPostgreSQL、MySQLを比較すると文字列、数値型の定義が異なるみたいですね。
ここらへんも関数と同じで違うものに移行する際は気をつけないと行けないポイントだと思います。
ただ日付型についてMySQLは独特の定義をしています。
Oracle、PostgreSQL：YYYYDDMMHHMISS
MySQL:%Y %D %M %h:%i:%s
全ての開発者が学ぶべき1つの言語

「どの言語を学ぶべきか」という議論が都内各所で流行しているようなので、FPGA論理合成の間に暇だったので私も書いてみることにしました。

## 全ての開発者が学ぶべき1つの言語

![](https://github.com/dlang/dlang.org/raw/master/images/d3.png)

## 1.D言語

D言語は[サーバーサイドのアプリケーション開発をリードできる言語](https://diamondmvc.org/)です。
モバイルゲームやAndroidアプリの開発、そしてエンタープライズWebアプリケーションの開発まで、非常に大きなマーケットに大胆かつ冒険的な野心的大挑戦が行えます。

頑強でスケーラブルなサーバーサイドアプリケーションを開発したいなら、あなたはD言語を学ぶべきです。どのように複雑なシステムであってもD言語で書けますし、様々なツールやテクノロジー、そしてコミュニティのサポートを得ることができないこともないこともないかもしれません。少なくともソースコードは公開されています。

**なぜD言語を学ぶ必要があるのでしょうか？D言語を使うことで、システムレベルの詳細事項やメモリ管理に手を入れる自由をポインタやCとの直接的なインターフェイスやインラインアセンブラで確保しつつ、いっぽうで、`unittest`や契約プログラミング・型や安全性を担保する豊富な属性・`template`や静的リフレクション・`range`や`std.algorithm`の機能により、アプリケーションのアーキテクチャ設計やコーディングに集中することができるのです。生成された実行ファイルを動かすのに面倒なVMは不要ですし、評判の悪いGCも`@nogc`属性を書くだけで簡単に排除できます。**

もしあなたがD言語を学ぶことを決心したなら、[DLang Tour](https://tour.dlang.org/tour/ja/welcome/welcome-to-d)をお薦めします。全ての基本コンセプトが程よいバランスで網羅されています。

## 2.D言語

D言語は、[世界中のスクールや大学でC++に挫折した人々によりひそやかに使われている言語](http://www.ie.u-ryukyu.ac.jp/~e085739/d.tuts.html)です。D言語を学ぶことで何が得られるかって？たくさんあります。

D言語は、スクリプト言語として使用することも可能ですし、オブジェクト指向言語として巨大なプロジェクトの開発に使うことも出来ます。

```console
$ rdmd --eval='writefln("hello,world!")'
hello,world!
```

さらにD言語は、[機械学習やAIやデータサイエンス等の新世代のテクノロジーと共に頻繁に使われるようになってきています](https://postd.cc/d-is-for-data-science/)が、それは全く不思議なことではありません。

私は個人的にD言語をスクリプト言語として使用しています。瞬間的に終わるコンパイルとネイティブコードの実行速度でアドホックなタスクをすぐに片付けることができます。

もしあなたがD言語を学ぶことに興味を持ったなら、[DLang Tour](https://tour.dlang.org/tour/ja/welcome/welcome-to-d)は最初に学ぶコースとしてお薦めです。

## 3.D言語

この1つのリストにおいて、D言語をD言語に置き換えたり、あるいはD言語をD言語に置き換えることは可能かもしれませんが、今日のWebの世界においてD言語を他の言語で置き換えることは出来ません。

D言語の用途はもはやサーバーサイド開発やUI開発にとどまりません。[emscripten](http://aba.hatenablog.com/entry/20130331/p1)や[WebAssembly](https://wiki.dlang.org/Generating_WebAssembly_with_LDC)の登場により、D言語はクライアントサイドのスクリプティング言語にも使用出来るようになりました。

もしあなたがD言語を学びたいなら、[DLang Tour](https://tour.dlang.org/tour/ja/welcome/welcome-to-d)は最良のオンラインコースです。

## 4.D言語

D言語を知らずして真のプログラマーになることは出来ません。厳しすぎる言葉かもしれませんが、これは私の短くそして無残な経験から断言できます。

D言語は、システム水準のプログラミング言語として使える言語ですし、過去数年間に「言語のポピュラリティ」の分野における競争で、20位くらいに来るとみんな盛り上がる感じでした。

もしあなたがこの素晴らしい言語を学びたいなら、[DLang Tour](https://tour.dlang.org/tour/ja/welcome/welcome-to-d)は最初の一歩としてお薦めです。

D言語はメインストリームじゃないのにもう割と古い言語の一つで、20年近くに渡ってどうにか開発を続けてきました。

D言語は、そのパフォーマンスの高さによって、特に[ゲーム開発者にとっては非常に重要な言語だと思ってもらえるといいな](http://dconf.org/2016/talks/watson.html)と思いました。

## 5.D言語

D言語は、過去20年間のベストプラクティスの蓄積によって産み出された言語です。[D言語は関数型言語でもあり](https://garden.dlang.io/)、オブジェクト指向とはまた別のパラダイムを提供します。プログラミングに関するあなたの考え方や感覚を改善することに役立つでしょう。

その他にも、Haskell等の様々な関数型言語が存在しますが、私はD言語エンジニアでもあるので、HaskellよりもD言語を学ぶ方が簡単だったということでD言語を選択しました。

もちろんHaskellにチャレンジするという方法も十分にありですが、多くのD言語エンジニアにとってはD言語を学ぶ方がより実践的であり実利的だと思います。

職業エンジニアとして、私は自己投資が自分のキャリアにおいて役に立つことを重視しています。あなたがD言語を学びたいなら、[DLang Tour](https://tour.dlang.org/tour/ja/welcome/welcome-to-d)は最初の一歩として良い選択です。

## まとめ

興味深い記事を執筆してくださった方や翻訳・紹介してくださった方々に感謝します。

## 追記

変に人気が出てしまったので追記させていただきます。

今年のアドベントカレンダーで入門記事などもやろうと思うので、ちょっとでも興味を持っていただけたらぜひ見てみてください！

https://qiita.com/advent-calendar/2018/dlang

こちらは世界一キュートなマスコットキャラであるD言語くんのアドベントカレンダーです。
ぶっちゃけD言語でなくてもD言語くんであれば許されるAdCです。

（雰囲気は過去のカレンダーからお察しください）

まだまだ空きがあるので奮ってご参加ください！

https://qiita.com/advent-calendar/2018/d-man
cancancanのload_resourceのまとめ

権限承認用に[CanCanCommunity/cancancan](https://github.com/CanCanCommunity/cancancan)を入れていましたが、`load_resource`が多機能で、認証不要な場面でも使いたくなるものでした[^1]。

## デフォルトの機能性

デフォルトでは、こんな動きをします。

```app/controllers/items_controller.rb
class ItemsController < ApplicationController
  load_resource
end
```

このように書いておくと、以下の動きをします。

* `new`アクション→`@item`に`Item.new`をしたものが入り、なおかつ権限設定上必須となる値がセットされる
* `create`アクション→`new`で行われる初期化処理にプラスして、`params`の解釈用に用意してあるメソッド（後述）を呼び出して`@item`を変更する
* `index`アクション→`@items`に`Item.accessible_by(current_ability)`が入る
* `show`・`edit`・`destroy`、基本7つ以外のアクション…`@item`に`Item.find_by(params[:id])`が入る
* `update`アクション…上のように`@item`が回収された上で、`params`の解釈用に用意してあるメソッド（後述）を呼び出して`@item`を変更する

これだけしてくれるので、アクション内で書くコードは大幅に減少します。`new`アクションなどは、空っぽになってしまうこともありえます。

### 自動で呼び出す`params`メソッド

以下のような優先順位で、存在するメソッドが呼び出されます。全てなければ何も起きません。

0. `load_resource`のオプションで`param_method: :method_name`のように指定した名前
1. `#{アクション名}_params`
2. `#{リソース名}_params`
3. `resource_params`

## カスタマイズする

もちろん、レールに乗っかってデフォルトの設定で使うのが楽なのは間違いないですが、そうは問屋が卸さない場面も多々あります。そのような場合は、自分で上書きすることもできます。

### 先に自分でロードする

一部のアクションだけ自分でロードしたい場合には、`load_resource`の前に`before_action`で`@item`をセットすれば、`load_resource`によるロードはバイパスされます。

### ネストする

ネストしたリソースの場合、`load_resource`を複数重ねることで両方をロードさせることができます。長くなりそうなので、詳しくは[公式のWiki](https://github.com/CanCanCommunity/cancancan/wiki/Nested-Resources)を見てください。

### 引数指定

`load_resource`に引数を足すことで、デフォルトでは名前から暗黙に設定されていた変数やクラス名も、手動設定できます。

* `only:`、`except:`…`before_action`に付ける同様の引数のように、アクションごとに`load_resource`を適用するかしないかを切り替えます。
* `through:`、`through_association`、`shallow:`、`singleton:`、`parent:`…リソースネスト関連のパラメーターです（詳細略）。
* `class:`…モデルのクラスを文字列、あるいは定数で指定します。
* `instance_name:`…インスタンス変数の名前を変更します（先頭の`@`は不要です）。コレクションの変数も、これの複数形になります。
* `find_by:`…モデル1つの取得を`fund_by_#{find_by}!`メソッドで行うように切り替えます。
* `id_param:`…モデルを特定する引数を`params[:id]`以外に切り替えます。
* `collection:`…`index`以外の、コレクションを取得するアクションを指定します。
* `new:`…`new`、`create`以外でモデルを新規作成するアクションを指定します。

[^1]: ただし、`can :manage, Model`のようにきちんと素通しにする形でセットしておかないと、うまく動きません。
名古屋の駅乗者数で単回帰分析 #2

前回までと反省
---

前回までは以下を参照
https://qiita.com/takinou/items/5cd236ef05c68304f09b

データ数確保のために、1990年とか2000年とか、古い時期のデータも入れていたのだけど、未開設の駅もそのまま放り込んでいたのでよくないと思った。
そこに何の路線も通っていないよ、だから利用者0人だよ、と言うのは正しいには正しいんだけど、データ的にはゴミじゃね? と言うことで除外することにする。

コードはここ。
----

[https://github.com/takinou/station_sim/blob/master/2_simple_linear_regression_nonzero.ipynb]


前回と変えたところ
----

路線数が非0のデータだけを元データとして採用する。

```
Nagoya_Station_data=Nagoya_Station_data[Nagoya_Station_data['lines']!=0]
```

散布図からも0が消えたことを確認。
![sample.png](https://qiita-image-store.s3.amazonaws.com/0/254176/a9aa7d50-3469-c9b4-857a-8a0a2b880e53.png)

あとは前回と同様に、単回帰分析をしてみる。

結果
---

相関係数
```
np.corrcoef(nz_datas['lines'], nz_datas['josha_num'])
array([[1.        , 0.85435272],
       [0.85435272, 1.        ]])
```
0.85だった。
前回は0.82なのでちょっと改善

回帰直線と散布図を見比べてみるとこんな感じ。
![graph2.png](https://qiita-image-store.s3.amazonaws.com/0/254176/6d0b53b4-2fa6-d821-309d-a88f50c3556c.png)




決定係数
---

決定係数は0.73だった。
前回は、0.68だったので、ちょっと改善。
やっぱ適当なデータは入れるべきではないなぁ。
PrometheusのAlertManagerだけZABBIXから使ってみる

# はじめに

ZABBIXで監視をしてメールでアラートを通知していて、以下のようなことに遭遇する人は多いと思う

- ログ監視をしていて連続でメールが飛んできてメールサーバが死んだり遅延したり散々な目に遭う
- SNMPTrap監視をしていて（ｒｙ
- メンテナンスなどのスケジュールが延長になり、ZABBIXメンテがあけてしまって大量のメールが（ｒｙ

ZABBIXはもうちょっとメールやアクションの実行に対してきめ細やかな制御ができるべきと切に思うが、そんなこと言ってもしょうがないので解決方法を考えていた。

# PrometheusのAlertManager

Prometheusの一部であるAlertManagerは、Prometheusが発生させたイベントを通知するための小さなサーバアプリケーションで、通知機能を持っています。
特徴的なのは、アラートをホスト、プライオリティやその他自分で定めたラベルなどによって短時間中に来たアラートをグループ化し、通知やインシデント化をまとめる機能を持っています。これをZABBIXで利用したいと思う。

# ZABBIXの設定

## AlertScriptの設定

雑に作っていて恐縮ですが、ZABBIXのアラートスクリプトのディレクトリに以下のようなファイルを置きます。

```python:/usr/lib/zabbix/alertscripts/zabbix_alertmanager.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import json
import requests

if len(sys.argv) < 4:
  print("Require Arguments 3 to,subject,body")

to=sys.argv[1]
subject=sys.argv[2]
body=sys.argv[3]

## to -> unused.
## subject -> Priority\tInstance\tGroup(commasep)\tAlertname
## body -> Alertmanager's annoation summary field.

hash = {}
hash["labels"] = {}

labels = subject.split("\t")
hash["labels"]["Priority"] = labels[0]
hash["labels"]["ProjectName"] = labels[1]
hash["labels"]["Instance"] = labels[2]
hash["labels"]["Group"] = labels[3]
hash["labels"]["alertname"] = labels[4]
hash["labels"]["system"] = "zabbix"

hash["annotations"] = {}
hash["annotations"]["summary"] = body

jsonstr = json.dumps([hash])

# 以下、AlertManager Output

json_data = jsonstr.encode("utf-8")
am_url = "http://localhost:9093/api/v1/alerts"
headers = {"Content-Type" : "application/json" }

r = requests.post(am_url, data=jsonstr, headers=headers)
```

## MediaTypeの設定

メディアタイプをこんな感じ。

| 項目 | 値 |
| :--- | :--- |
| Name | AlertManager |
| Type | Script |
| ScriptName | zabbix_alertmanager.py |
| Enbled | Checked |


## AlertManagerメディアタイプを持つユーザの作成（または既存ユーザへのMedia追加）

AlertManagerメディアタイプを持つユーザを作っておきます。メールアドレス欄はAlertManager側で使えないので、何でもいいです。

## Actionの作成

AlertManager用のActionを作ります。

| 項目 | 値 | 補足 |
| :--- | :--- | :--- |
| Name | AlertManager Action など 何でも良い | |
| Default Subject | {TRIGGER.SEVERITY}	ProjectName	{HOST.NAME1}	{TRIGGER.HOSTGROUP.NAME}	{TRIGGER.NAME} | タブ区切りなので、どこかテキストエディタに書いてからWebUIに貼る プロジェクト名はZABBIXが複数ある前提で入れている |
| Default Message | {ITEM.NAME1}:{ITEM.VALUE1}<br>{TRIGGER.DESCRIPTION}|アラートのサマリーフィールドとしてふんわりとしたテキストを入れる感じにしているので、入れたい情報を入れれば良い|
| Recovery Message | 無効 |

以上でZABBIX側の設定は完了。

# AlertManagerの設定

ちょっと正しい流儀で書いてる気がしなかったのでAlertManagerの設定は省略しますが、9093ポートでデフォルトのような設定で起動して、通知設定を適切に行えばZABBIXからアラートを飛ばせるようになります。
ただし、今回はリカバリメッセージを切っているように、復旧の通知は行うようにしていません。

# 課題

- リカバリメッセージどうする問題
- APIバージョンが古いかもしれない 今Github見に行ったらAPIv2とか書いてある…
- AlertManagerの設定をちゃんとまとめるとか、Git管理して自動的にデプロイされるようにするとか云々
- 通知先の管理 ZABBIX上のUIと切り離されてAlertManagerのyamlで管理しないといけなくなるので、その手間など

# 2019.10.24追記

どうやらamtoolというCLIがあるので、amtoolをZABBIXサーバにインストールし、これをアラートスクリプト指定して適切にデータを渡すように組むのが良さそうです。
（APIが変わったら対応面倒なので、やはりちゃんとSDKやCLIのような専門に任せたほうが良い）
上手く送るデータを設定すれば、復旧も管理できるようになりますね。

https://qiita.com/sugitak/items/49f5cd93628564ac88f7
[Open3dのお勉強]crop用jsonファイルを理解する

open3dを勉強するにあたって、
http://www.open3d.org/docs/tutorial/Basic/pointcloud.html
で読み込まれるjsonフォーマットが分からなかったので、調べました。

https://github.com/IntelVCL/Open3D/blob/master/examples/TestData/Crop/cropped.json
```json
{
	"axis_max" : 4.022921085357666,
	"axis_min" : -0.76341366767883301,
	"bounding_polygon" : 
	[
		[ 2.6509309513852526, 0.0, 1.6834473132326844 ],
		[ 2.5786428246917148, 0.0, 1.6892074266735244 ],
		[ 2.4625790337552154, 0.0, 1.6665777078297999 ],
		[ 2.6579576128816544, 0.0, 1.6819127849749496 ]
	],
	"class_name" : "SelectionPolygonVolume",
	"orthogonal_axis" : "Y",
	"version_major" : 1,
	"version_minor" : 0
}
```



読んだソースはこれ。
https://github.com/IntelVCL/Open3D/blob/master/src/Visualization/Utility/SelectionPolygonVolume.cpp

パラメータ
--------------------------
|変更不可パラ      |値|
|:-----------------|:--:|
|"class_name" : |"SelectionPolygonVolume",|
|"version_major" : |1,|
|"version_minor" : |0|


|変更可パラ      |値    | コメント    |
|:---------------------------|:---------:|:------------|
| "orthogonal_axis" :| "Y", 　             |cropする軸をXYZから選ぶ。 |
|"axis_max" : |2.02,     |"orthogonal_axis" での最大値|
|"axis_min" : |-0.76,　|"orthogonal_axis" での最小値|　
|"bounding_polygon" : |[...]    |"orthogonal_axis" を0で固定して、cropする多角形を指定|
YouTubeの360度VR動画をwebに埋め込む時のスマフォ・タブレット対応

webサイトにYoutubeの360度VR動画を埋め込むと、PCだとそのまま見れるのですが、スマフォとタブレットのブラウザ再生だと対応してないので、スマフォとタブレットでifreamをクリックしたら、アプリに飛ばすようにしました。



```html:sample.html
<a href="[Youtube VR動画URL]">
	<div class="player">
		<iframe id="vr_iframe" width="560" height="315" src="" frameborder="0"></iframe>	
	</div>
</a>
```
```javascript:script.js
/*ユーザーエージェント判定でスマホ・タブレットはVR動画のiframe内のクリックを無効にする */
var ua = navigator.userAgent;
if(ua.indexOf('iPhone') > 0 || ua.indexOf('iPod') > 0 || (ua.indexOf('Android') > 0) && (ua.indexOf('Mobile') > 0) || ua.indexOf('Windows Phone') > 0) {
	$('#vr_iframe').css('pointer-events','none');
}else if(ua.indexOf('iPad') > 0 || ua.indexOf('Android') > 0){
	$('#vr_iframe').css('pointer-events','none');
}else{}

```

iframe内クリックを無効にすれば、アンカータグのリンクが有効になるので、スマホ/タブレットで動画をクリックすると、「"Youtube"で開きますか？」のメッセージが出現し、アプリで開けば360度VR動画を再生できます。
超簡易画像アップローダーの製作

#始めに
ネット上に画像をアップロードしたいという必要にかられたのですが、FTPを使ってアップデートをするのは面倒。ZENPhotoなどのような本格的な画像管理CMSの導入までは至らない。しかしかといってCGIを使った既存のアップローダーは投稿件数に制限があったり、10年以上サポートが止っていることなどから自作することにしました。

必要要件は以下の通り。
1. 現状において削除はFTPで行っても構わない。
2. 画像のみのアップローダーとする
3. 大きすぎるファイルは排除する
4. アップ後のファイル名は元のファイル名では無くプログラムで決めたファイル名を使う

ご存じの方も多いでしょうが、PHPにはファイルアップロードに関する機能が内蔵されており、比較的容易にフォームからファイルのアップロードを行うことができます。

#コード

```HTML:index.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>画像のアップロード</title>
</head>
<body>
<form action="upload.php" method="post" enctype="multipart/form-data">
  ファイル：<br />
  <input type="file" name="upfile" size="30" /><br />
  <br />
  <input type="submit" value="アップロード" />
</form>
</body>
</html>
```

```PHP:upload.php
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>画像のアップロード</title>
</head>
<body>
<p><?php

const FILE_FOL = "files/";

//変数の初期化
	$check = null;
	$newfilename = null;
	$msg = null;

//元ファイル名の先頭にアップロード日時を加える

	$ext = pathinfo($_FILES["upfile"]["name"], PATHINFO_EXTENSION);
 	$newfilename = date("YmdHis").mt_rand().".".$ext;

// ファイルがアップデートされたかを調べる
	if(is_uploaded_file($_FILES["upfile"]["tmp_name"])) {
		$check = 1;
	} else {
		$check = 0;
		$msg = "ファイルが選択されていません。";
	}

	if ($check == 1) {
		if ($_FILES['upload']['size'] > 1000000) {
			$check = 0;
	    	$msg = 'ファイルサイズを小さくしてください';
		}
	}

//画像か調べる

	$file_pass = $_FILES["upfile"]["tmp_name"];
	if ($check == 1) {
	    if(file_exists($file_pass) && $type = exif_imagetype($file_pass)){
	        switch($type){
	            //gifの場合
	            case IMAGETYPE_GIF:
	            break;
	            //jpgの場合
	            case IMAGETYPE_JPEG:
	            break;
	            //pngの場合
	            case IMAGETYPE_PNG:
	            break;
	            //どれにも該当しない場合
	            default:
	            $msg =  "gif、jpg、png以外の画像です";
	        }
	    }else{
	        $msg =  "画像ファイルではありません";
	        $check = 0;
	    }
	}

//例外処理を全てクリアしたらファイルをアップする
	if ($check == 1) {
	  if (move_uploaded_file($file_pass, FILE_FOL.$newfilename)) {
	    chmod(FILE_FOL. $_FILES["upfile"]["name"], 0644);
	    print $newfilename. "としてファイルをアップロードしました。<BR>";
		print "<a href=".FILE_FOL.$newfilename. ">ファイルを確かめる</A><BR>";
		print "<img src=".FILE_FOL.$newfilename." width=400>";
	  } else {
	    print "ファイルをアップロードできません。";
	  }
	} else {
	print $msg;
	}
	print "<P><a href=index.html>戻る</A>";
?></p>
</body>
</html>
```

あとはこの二つを格納したディレクトリの下にFileディレクトリを作成し、FTPソフトなどでパーミッションを 777 に設定すれば完成です。フラグ処理をすることで例外処理の拡張性を増しております。なお、技術的な解説の詳細は最後の参考文献を参照ください。

#まとめ
例外処理に躓きもありましたが、簡易的なものであれば殆どPHPの知識が無くても構想を含め2～3時間で完成出来たのには驚きました。これから本格的なものを作成するとなると大変なのも容易に想像が可能でありますが･･･。

#参考文献
- [ファイルのアップロード(PHP Labo)](http://www.php-labo.net/tutorial/php/upload.html)
- [PHPでファイルアップロードを実装する方法(UX MILK)](https://uxmilk.jp/14317)
- [PHPでのファイルアップロードとエラーチェックの方法
(flatFlag)](https://www.flatflag.nir87.com/move_uploaded_file-970)
OSXでのプラグイン作成時のニッチな注意点

OSXでのプラグイン作成時のすごくニッチな注意点となります。
結論から書くと
**「NSPrincipalClassでは"-"は使えないので"_"を使え！！」**　
です。

* * *

以下例。

プラグインをロードし、使うためには

```swift:test.swift
if let bundle = Bundle.init(url: "プラグインのURL") {
    if let cls = bundle.principalClass as? NSObject.Type, let plugin = cls.init() as? PluginInterface {
        // ここで　plugin を使ってなんやかんやする
    }
}
```

というようなソースになります。
bundle.principalClassに、プラグインとして期待するクラスが格納されている前提ですね。
で、この期待されるクラスを取得するためにはプラグイン側のソースのInfo.plistにて、

```swift:Info.plist
Principal class プラグインクラス

という表記をする必要があります。XMLで表記するとこんな感じ。

<key>NSPrincipalClass</key>
<string>final-fantasy.pluginMain</string>
```

ここで、final-fantasyはそのプラグインバンドル名になるのですが、
この表記だと、bundle.principalClassで、思った通りのpluginMainクラスが取得できません。
正解は
	<key>NSPrincipalClass</key>
	<string>final_fantasy.pluginMain</string>
というように "-" ではなく "_" を使用する必要があります。

appIDなどでは普通に"-"が使えるのに、ここでは"-"を使うと全く通用しないようで、
マニュアル等にも記載が見つからなかったため地味にハマることもあるのではないかとおもい、ここに記させていただきました。

参考リンク
[xcodeのプラグインを作る方](https://qiita.com/gmaesak/items/35ecca9638dbc6d2bdfd　"xcodeのプラグインを作る方")
win-acme で証明書を発行する

# この記事は本当に必要？
と思ったけれど、似た記事がQiitaでは見つからず、やっぱり無いよりはあったほうがマシかなということで、備忘録的に書き残しておくことにしました。

# 何をするのか？
普段は自宅の Windows 7 で Apache を動かして、自宅サーバにしているが、気づいたらサーバ証明書が1年以上過ぎていたので更新しようかと。

(そのサイトはIPアドレスでアクセスしてきた時に面倒な事が無い様に表示していた、いわゆるダミー的なものだったので、全然気付かず、影響もほぼまったく無かった。むしろ抑止効果という意味ではそのままでも良かったのかも……？)

今回何が一番ハマったかというと、証明書がどこに出力されるのか？ということだったので、最後にそれを書いてお仕舞いにします。

# いざ

### win-acme の入手
https://github.com/PKISharp/win-acme/releases
こちらから最新版を入手できます。
執筆時(2018年11月6日)現在は、1.9.12.1 が最新でした。

### zip を解凍
### コマンドプロンプトを管理者権限で起動
解凍した win-acme のディレクトリまで移動し、以下をそれぞれの環境に合わせて書き換えてから実行。
(今回はドメインが `www.example.com` 、公開ディレクトリが `C:\htdocs\www\com.example\public` という仮定で例示しています。)

``` command:Command
letsencrypt.exe --plugin manual --manualhost www.example.com --webroot "C:\htdocs\www\com.example\public"
```

途中で何か聞かれたらしっかり読んで、答えてください。

無事に出力が終わると、
`C:\ProgramData\win-acme\httpsacme-v01.api.letsencrypt.org`
こちらに証明書類が出力されています。

以上です。

うまくいきましたでしょうか？

# あと書き
実はここに書いている内容は https://github.com/PKISharp/win-acme/wiki/Apache-2.4-Basic-usage これがほぼそのまんまなのですが、最後の最後、出力されるディレクトリが微妙に実際とは違って、少し混乱してしまいました。

このドキュメント(Wiki?)は少し古かったようです……。
OpenLayersで中心座標（緯度・経度）を取得する

OpenLayersのデフォルトの地図投影法はWeb (球面) メルカトル (EPSG:3857) となっているため、中心座標を地理座標系（緯度・経度）で取得するためには以下のいずれかの方法を用いる必要がある。

### (1) Webメルカトルの座標を変換する

`ol.proj.transform` メソッドでWebメルカトル (EPSG:3857) 座標を地理座標系 (EPSG:4326) に変換する。

```javascript
let coordinate = ol.proj.transform(map.getView().getCenter(), 'EPSG:3857', 'EPSG:4326');
```

### (2) 地理座標系の投影法で地図を表示する

表示される地図の形が変わってしまうが、地理座標系を使った投影法 (EPSG:4326) で地図を表示すれば、取得できる座標は緯度・経度になる。

```javascript
new ol.View({
	projection: 'EPSG:4326',
		center: [139.7528, 35.685175] // 緯度・経度を直接指定できる
	})
});
```

### 実装例

[CodePen - OpenLayers Get Center Coordinate](https://codepen.io/unhurried/pen/KrKjKN)

### 参考

* https://openlayers.org/en/latest/doc/faq.html#what-projection-is-openlayers-using-
* http://blog.godo-tys.jp/2013/06/10/2241/
rspecのmockでつまづいた話

# この記事で書くこと
rspec-railsでmockを使用してテストする方法をまとめました。ただメソッドなどを紹介するというよりは、対象のコードがいて、それをテストするといった少しだけ実践的な方法で紹介します。

# 使用したコード
今回はcontroller specを使用します。（現在は、request specに移行することが推奨されているみたいです。）
テスト対象とテストコードは以下になります！

① テスト対象のコード。

```ruby:app/controller/users_controller.rb
・・・
def create
    data = request.body.string
    user = User.new
    if user.change_allelgy_status(data) == 0 then
      render nothing: true, status: 200
    elsif 
      render nothing: true, status: 400
    end
 end
・・・
 ```

② テストコード。

```ruby:spec/controllers/users_controller_spec.rb
require 'rails_helper'

RSpec.describe UsersController, type: :controller do

  describe "POST #create" do
    context "when the allergy status change process is successful" do
      it "has 200 status code." do
        user = instance_double(User)
        allow(User).to receive(:new).and_return(user)
        allow(user).to receive(:change_allelgy_status).and_return(0)
        post :create
        expect(response).to have_http_status(200)
      end
    end
  end
end
```

# 解説
## 1. インスタンスmockの作成
```ruby
user = instance_double(User)
```
Userクラスのインスタンスmockを作成しています。これを作成することで、`user.change_allelgy_status`のような**インスタンスメソッド**をmockから呼び出すことができます。
また、似たような処理に`User = class_double(User)`がありますが、これは`User.new`のように**クラスメソッド**mockから呼び出したい時に使用します。

## 2. スタブの作成
今回、個人的に1番ハマった処理です。まず、上手くいったコードからご紹介します。

```ruby
allow(User).to receive(:new).and_return(user)
allow(user).to receive(:change_allelgy_status).and_return(0)
```
これは、`user = User.new`と`user.change_allelgy_status`をそれぞれスタブにしたものです。

`allow(User).to receive(:new).and_return(user)`は、Userクラスのnewメソッドが呼ばれた時に、user（インスタンスmock）を返すという意味です。

`user.change_allelgy_status`は、userインスタンスのchange_allelgy_statusメソッドが呼ばれた時に、0を返すという意味です。以下の分岐に入るように返り値を0にしています。

```ruby
if user.change_allelgy_status(data) == 0 then
  render nothing: true, status: 200    # <= ここの分岐！！
elsif 
```

以上が正しいコードでした。それでは、次に僕がハマったパターンを紹介します。

```ruby
allow(user).to receive(:change_allelgy_status).and_return(0)
```
はじめ、上記のコードだけ書いてテストしたところ、なぜかスタブの`change_allelgy_status`が呼ばれずに、実処理が実行されてしまいました。この原因は、おそらく下記だと思います。

```ruby:app/controller/users_controller.rb
・・・
def create
    data = request.body.string
    user = User.new  
    # <= ここでuserインスタンスを作成しているため、次の処理で呼ばれる
    #　　　　　　　　user.cahnge_allelgy_statusは、このuserインスタンスが使用される。
    if user.change_allelgy_status(data) == 0 then
      render nothing: true, status: 200
    elsif 
      render nothing: true, status: 400
    end
 end
・・・
```
従って、`User.new`から作成したuserインスタンスをスタブ化し、スタブ化されたインスタンスからchange_allelgy_statusを呼び出すことになりました。

```ruby
allow(User).to receive(:new).and_return(user)
allow(user).to receive(:change_allelgy_status).and_return(0)
```

## 3. 期待値の確認
`post :create`
createアクションにpostリクエストを投げて、処理を開始します。

`expect(response).to have_http_status(200)`
postリクエストのレスポンスコードが200であることを確認しています。

# まとめ
簡単ではありますが、rspecでmockを使用したテストをご紹介しました。実際に自分がつまづいた点も交えて記載したので、参考にしてもらえたら幸いです。
C# × Docker で基礎学習 Part1 〜コンソールアプリ編〜

C# × Dockerで色々な構成のアプリを作成していきます。
手始めにコンソールアプリを作成します。

# 開発環境

* macOS High Sierra
* Docker for Mac Version 18.06.1-ce-mac74
* .Net Core 2.1.4
* Visual Studio Code

# 作成するアプリ

簡単なC#コンソールアプリケーション

# アプリ作成

最初にコンソールアプリを作成します。
アプリを作成したいフォルダに移動し、以下のコマンドを実行します。

```bash
$ dotnet new console
```
実行すると以下のようにファイルとフォルダが作成されます。

```bash
# フォルダ名がアプリ名(csprojのファイル名)になる
.
├── App.csproj
├── Program.cs
└── obj
    ├── App.csproj.nuget.cache
    ├── App.csproj.nuget.g.props
    ├── App.csproj.nuget.g.targets
    └── project.assets.json
```

実行してみます

```bash
$ dotnet run
Hello World!
```

# Dockerの準備

Dockerfileを作成し、Dockerで実行するための設定をします。
以下の内容でDockerfileを作成します。

```bash:Dockerfile
FROM microsoft/dotnet:2.1-sdk
WORKDIR /app

# csprojをコピーし、依存パッケージを取得
COPY *.csproj ./
RUN dotnet restore

# プログラムのコピー
COPY . ./

# リリース資材をoutフォルダに出力
RUN dotnet publish -c Release -o out

# プログラム実行
ENTRYPOINT ["dotnet", "out/App.dll"]
```

ビルドします。

```bash
# -tオプションはリポジトリ名を指定（好きな名称でOK)
$ docker build -t dotnet-console
```

実行してみます。

```bash
$ docker run --rm dotnet-console
Hello World!
```

今回は以上です。

実際にPGはしませんでしたが、もちろん任意のプログラムを作成してから
Dockerでビルド・実行すれば任意の文字を表示することも可能です。

# 次回予告

次回はWEBアプリ(ASP.NET MVC)を作成してDockerで実行してみようと思います。
[C# × Docker で基礎学習 Part2 〜WEBアプリ編〜](https://qiita.com/MasanoriIwakura/items/556b90d45a3099ac4ec0)

# 参考サイト

https://docs.microsoft.com/ja-jp/dotnet/core/docker/docker-basics-dotnet-core
Macの写真アプリの内容をWindowsに移す

Macの写真アプリからWindowsへの写真移行を行っており、その手順メモです。
最終的に手順にまとめる予定ですが、未完成です。

写真アプリでアルバムであったものを
Windowsではフォルダとして移行することを目標にしています。
アルバムに属していない写真の扱いは検討中です。

#アルバム構造の取得
```sql
select 
  RKMaster.modelID
  , RKMaster.uuid
  , RKMaster.imagePath
  , RKAlbum.name
  , RKAlbum.folderUuid
  , RKAlbum.albumType
  ,RKAlbum.modelID
from
  RKMaster
  left outer join RKVersion
    on RKVersion.masterID = RKMaster.modelID
  left outer join RKAlbumVersion
    on RKAlbumVersion.versionID = RKVersion.modelID
  left outer join RKAlbum
    on RKAlbum.modelID = RKAlbumVersion.albumID
where
  RKAlbum.isInTrash != 1
  and RKAlbum.name != 'Last Import'
  and RKMaster.isInTrash != 1;
```
```sql
select distinct
  RKAlbum.name
  , RKAlbum.modelID 
from
  RKMaster 
  left outer join RKVersion 
    on RKVersion.masterID = RKMaster.modelID 
  left outer join RKAlbumVersion 
    on RKAlbumVersion.versionID = RKVersion.modelID 
  left outer join RKAlbum 
    on RKAlbum.modelID = RKAlbumVersion.albumID 
where
  RKAlbum.isInTrash != 1 
  and RKAlbum.name != 'Last Import' 
  and RKMaster.isInTrash != 1;
```
#アルバム名の濁点・半濁点が分離しているので変換する
NFD→NFC変換ツール
http://tsuyobi.heteml.jp/html/tools/nfd2nfc/
ローカル環境に諸々をインストールせずにRails新プロジェクトを作成する

## 概要

ローカルにインストールされているRailsに影響されない、最新のRailsを使ってプロジェクトを新規作成する手順をまとめておきます。


## プロジェクトの作成

### Gemfileの作成

フォルダ新規フォルダを作成し、その中にGemfileを作ります。

```ruby:Gemfile
source "http://rubygems.org"
gem 'rails'
```


### Railsをインストール

Railsを`vendor/bundle`フォルダ以下にインストール。

```
$ bundle install --path vendor/bundle
```


### Railsプロジェクトを作成

```sh
$ bundle exec rails new example --skip-bundle

# postgreSQLを使用する場合は以下のコマンドを実行
$ bundle exec rails new example -d postgresql --skip-bundle
```

注意:`--skip-bundle`を忘れないように

`--skip-bundle`を付けてやらないと、ローカルの環境にインストールしてしまいます。

プロジェクトを作成したら、Railsをインストールするために使った諸々のファイルを削除してOK。

```
$ rm -f Gemfile
$ rm -f Gemfile.lock
$ rm -rf .bundle
$ rm -rf vendor/bundle
```


## Railsプロジェクトの環境セットアップ

### プロジェクト用のgemインストール

```
$ cd example
$ bundle install --path vendor/bundle
$ echo '/vendor/bundle' >> .gitignore # GitHubなどを利用している場合は実行しておくと良い
```


### Railsプロジェクトの起動

以下のコマンドを実行して、http://localhost:3000 にアクセスできたら成功です。


```
$ bundle exec rails db:create
$ bundle exec rails server
```
golangアプリケーションのdockerイメージを小さくしたい

# なぜやるの?
dockerでアプリを動かすときdocker imageのサイズが大きくなる
このimageサイズをできるだけ小さくしたい
# どうやるの?
今回はdocker fileがメインなのgoファイルは共通にしている
使用するプログラムは以下になる
main.go

```go
package main

import (
  "fmt"
  "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintln(w, "Hello, World")
}

func main() {
  http.HandleFunc("/", handler)
  http.ListenAndServe(":8080", nil)
}
```
簡単なwebサーバでこれを動かして`curl`を叩くと`Hello, World`が帰ってくる
ちなみにディレクトリ構成は以下のようになっている  

## 今までのやり方
比較のため今までのdocker fileを紹介する

before/dockerfile

```dockerfile
FROM golang:1.10-alpine3.7
ADD ./ ./
RUN go build main.go
CMD [ "/go/main" ]
```
go build周りのことは簡単にしている
これを`docker build`してみる

```bash
$ docker build -t golang-docker-before before/

Successfully tagged golang-docker-before:latest
```
これが出てきたらbuildは正常に終わっているだろう
次に`イメージのサイズを見る

```bash
REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
golang-docker-before   latest              b289ef900ec0        3 minutes ago       264MB
golang                 1.10-alpine3.7      7f9031684cc1        3 days ago          257MB

```
さっき作ったgolagn-docker-beforeのイメージサイズはどうだろうか?
264Mある....でかい
そもそもgolangのイメージが大きい
これを小さくしていく

## 何が必要か
golangで作成したアプリには何が必要だろうか?
golangでbuildすると一つのファイルが吐き出される
つまりこれだけアレばいいはずである
今回でいうとmain.goでもその他パッケージでもなくmainが必要である

## イメージを小さくする
mainのファイルさえあればいいのでmainのファイルをbuild時に取り出す
そこでdockerでマルチステージビルドを使う
マルチステージビルドについては[docker docs](https://docs.docker.com/)を見るといいだろう
docker fileは以下のようになる

after/dockerfile

```dockerfile
FROM golang:1.10-alpine3.7 as build
ADD ./ ./
RUN go build main.go

FROM alpine:latest
COPY --from=build /go/main /app/main
CMD [ "/app/main" ]
```
docker fileを見てみよう最初のFROMではイメージの横に`build`というのがついている.これは任意の文字をつけることができる
golangのimageを使って`go build`を行っている
吐き出されたmainはどこにあるかというと`/go/main`にあるのでそれだけを取り出す
２つ目にFROMでイメージサイズが小さいalpineを使用する.
COPYで`--from=build`でどのimageからCOPYからコピーしてくる`build`は最初のFROMでつけたものを使う
そして`/app/main`に持っていく
最後にCMDを指定してあげて終了

## 修正後のimageサイズは

```bash
$ docker build -t golang-docker-after after/
$ docker images

golang-docker-after    latest              c9e1ed0e2383        38 minutes ago      11MB
<none>                 <none>              fece0e20da1f        38 minutes ago      264MB
golang-docker-before   latest              b289ef900ec0        About an hour ago   264MB
golang                 1.10-alpine3.7      7f9031684cc1        3 days ago          257MB
alpine                 latest              196d12cf6ab1        7 weeks ago         4.41MB
```
golang-docker-afterとgolang-docker-beforeのイメージサイズを比べてみる

結果は以下のようになる
golang-docker-after:11MB
golang-docker-before:264MB

## まとめ
そもそもimageサイズを小さくするメリットは`docker pull`が速くなることだろう
これはdocker pullを頻繁にやる環境では有効的だと考える.
今回使用したコードは[github](https://github.com/aeleniumfor/golang-app-docker)で見ることができる

ありがとうございました
【挫折する前に】 Ruby  引数がイマイチわからない人へ

プログラミング初心者がまず初めにつまづくのが**引数**ではないでしょうか。
「引数とはメソッドに渡す情報のことで…」なんて言われても最初はピンとこない人も多いと思います。
今回はそんな**引数**をわかりやすく記事にまとめてみました。
かなり色々なことを省略していますが、引数の概念がわかってもらえたらなと思います。

###この記事が参考になりそうな人
- 「引数がわからなくて挫折しそう！」という初心者の方
- 「わかりそうだけどイマイチわからない」という方


##引数とは
一応あらためて教科書的に説明をしておくと、引数とは
**メソッドの値をメソッドの外に渡す仕組み**のことです。
ん〜、やはりこの説明では？？？なので解説していきます。

##そもそも、なぜ引数を使う必要があるのか？
一言でいうと、**なんども同じプログラムを書く手間が減るから**です。
もし引数を使わないと、同じメソッドを何度も定義したりしなくてはいけないので、手間や時間もかかりますし、コードの可読性(見易さ)が悪くなります。

この記事では難しい説明は極力省いた方がいいと思うので、今の所はひとまず
「引数を使う事でプログラミングが楽になる」
というイメージでいいんじゃないかと思います。

##実際に引数を使ってみる
では、実際に引数がどのような役割で、どのように楽になるかをみていきます。
例えば以下のような足し算をするメソッド「tashizan」を作ってみます。

```ruby:sample.rb
def tashizan
10 + 10
end
puts tashizan
=>20
```

10 + 10という計算をするメソッドを定義し、20という値を出力できました。

これで完結するプログラムであれば上記のままでも問題ないのですが、例えば同じ要領で20 + 20 , 30 + 30・・・という計算をしたい場合、また１からメソッドを作って書くのは面倒ですよね？
**そこで引数の登場です。**
「hikisu」という名前で引数を使ってみたいと思います。
※今回はメソッド名・引数名を理解しやすいようにローマ字表記にしていますが、通常は英語かつ、他の人がみてもわかりやすい名前にするのが一般的です。

```ruby:sample.rb
def tashizan(hikisu)
hikisu + hikisu
end
puts tashizan(hikisu)
```
さて、メソッドと引数が書けました。
しかし、これでは数字がどこにも入っていないため計算ができませんよね？
そこで一番下に記述した**puts tashizan(hikisu)**の**(hikisu)**のなかに数値１０を入れてみます。

```ruby:sample.rb
def tashizan(hikisu)
hikisu + hikisu
end
puts tashizan(10)
=>20
```
無事計算できてますね。先ほどと同様、20という結果が得られました。

さて、ここからが**引数を使うメリット**です。
別の数値を引数として渡してあげると複数の出力を得ることができます。

```ruby:sample.rb
def tashizan(hikisu)
hikisu + hikisu
end
puts tashizan(10)
puts tashizan(20)
puts tashizan(30)

=>20
=>40
=>60
```
メソッドを新しく定義することなく、引数の数値を変えるだけで10+10,20+20,30+30の結果が出力できました。
かなり楽になったと思いませんか？もっと複雑なメソッドであればより便利さを実感できます。

##少し応用してみる
前項の例では同じ数字の足し算しかできませんでした。
では、違う数字の足し算をするにはどうすればいいか？
**簡単です。その場合は引数を増やせば対応できます。**

```ruby:sample.rb
def tashizan(hikisu, hikisu2)
hikisu + hikisu2
end
puts tashizan(10, 20)
=>30
```
「hikisu2」という引数を追加し、値を20にしました。
10＋20で30という結果が得られています。
このように引数が複数ある場合、左から**第一引数・第二引数**と数えます。

##まとめ
* 引数とは・・・メソッドの値をメソッドの外に渡す仕組みのこと。
* メリット・・・なんども同じプログラムを書く手間が減る。
* 複数の値を扱うには引数を増やす。

いかがでしたでしょうか？
引数を使う意味や便利さが少しはわかっていただけたでしょうか？
今回はわかりやすさを重視したので、色々な部分を省きました。
実際は今日やった部分に対して、実引数、仮引数、戻り値などという名前が付いますが、それはまた別の記事で書いていますので、興味のある方は[【挫折する前に】Ruby 引数がイマイチわからない人へ 発展編]
(https://qiita.com/yossy_sa/items/536913fd58f90d6811f7) をお読みください。
jQuery学習

#jQuery初歩の初歩

基本系

```
$('セレクタ').メソッド（引数）;
```

hideメソッド（要素を隠す）

```
$('h1').hide();
```

fadeOutメソッド（アニメーション速度を指定して要素を隠す）

```
$('h1').fadeOut();

$('h1').fadeOut(1500);
#引数でアニメーションの速度を1500ミリ秒（1.5秒）に指定
```

slideUpメソッド（アニメーション速度を指定して下から隠す）

```
$('h1').slideUp();

$('h1').slideUp(1500);
#引数でアニメーションの速度を1500ミリ秒（1.5秒）に指定
```

セレクタの指定（classとID）

```
#IDの場合
$('#list').css('margin','20px')
#クラスの場合
$('list').css('margin','20px')
```

隠れた要素(CSSでdisplay: none;)の表示、非表示

```
$('img').show();
```

アニメーション付きで要素を表示

```
$('img').fadeIn('slow');#引数にslowを指定するとゆっくり表示

$('img').slideDown('slow');#引数にslowを指定するとゆっくり表示

```


イベントの指定

```
$('h1').イベント名(function(){
     イベント発生時に実行したい処理
});
```

clickイベント

```
$('h1').click(function(){
     $('#text').hide();#クリック時に要素を隠す
});
```

CSSメソッド（要素のCSSを変更するメソッド）

```
$('h1').css('プロパティ','値')
```

htmlメソッド（htmlの中身も変えることができる）

```
<p>うおー<p>

$('p').text('ぬあー！')；
$('p').html('<span>おりゃー！</span>')；
```

this構文(そのイベントが起こった要素を指定できる)
例はリストのliの場合

```
$('li').click(function(){
  $(this).css('color', 'red');
})
```

複数回同じjQueryオブジェクトを使うときは変数にする。

```
$('div').css('color', 'red');
$('div').html('jQuery');
$('div').fadeOut();
```

```
var $div = $('div');#変数の頭には$をつける慣習

$div.css('color', 'red');
$div.html('jQuery');
$div.fadeOut();
```

同じjQueryオブジェクトを不空数回使用するときはメソッドチェーンを使うこともできる。

```
$('div').css('color', 'red').html('jQuery').fadeOut();
```
findメソッド（自分よりも下の階層の要素から指定したセレクタの要素を取得する）
childrenメソッド（自分の直下の子要素のセレクタだけを取得）

```
<div id="wrapper">
  <a href="#">リンク１</a>
   <p>
     <a href="#">リンク２</a>
   </p>
</div>
```

```
$('#wrapper').find('a').css('color', 'red');
$('#wrapper').children('a').css('color', 'red');
```

hoverイベント（マウスを乗せた時の処理）

```
$('セレクタ').hover(function(){
       マウスをのせた時の処理  },
       function(){マウスをはずした時の処理
});
```
React Native原因不明のエラーの解決方法

React Nativeはv1.0にも達しておらず、原因不明なエラーが発生し、ビルドできないことがあります。
原因不明なこともあり、下記のようなエラーメッセージが表示されます。

```
 This might be related to https://github.com/facebook/react-native/issues/4968
 To resolve try the following:
   1. Clear watchman watches: `watchman watch-del-all`.
   2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
   3. Reset Metro Bundler cache: `rm -rf /tmp/metro-bundler-cache-*` or `npm start -- --reset-cache`.                          4. Remove haste cache: `rm -rf /tmp/haste-map-react-native-packager-*`. (null))
```

問題究明するよりも、指示通りキャッシュを削除して解決することがあります。

```
watchman watch-del-all && rm -rf node_modules/ && yarn cache clean && yarn install && yarn start -- --reset-cache
```

## 参考
https://github.com/facebook/react-native/issues/4968
Kotlin 1.3.0, Spring Boot 2.1.0, OpenJDK 11.0.1 に更新した時の手順メモ

先日、開発中のプロダクトをタイトルの構成に更新したので、その時の作業メモを書きました。
IDE は IntelliJ IDEA を使用しています。

##更新前
- Kotlin 1.2.7
- Spring Boot 2.0.4
- gradle 4.6
- Java 8

## 更新後
- Kotlin 1.3.0
- Spring Boot 2.1.0
- gradle 4.10.2
- Java 11.0.1 (OpenJDK)

## Kotlin を 1.3.0 へ更新
`gradle build` を行ったが特に何事もなく正常に終了。

## Spring Boot を 2.1.0 へ更新
`gradle build` 実行時に `BeanDefinitionOverrideException` が発生したため `application.yml` に以下を設定し、build 成功。

```
spring.main.allow-bean-definition-overriding: true
```

## gradle 4.10.2 へ更新
`gradle-wrapper.properties` を以下に更新。

```
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip
```

`jaxb-api` が `JDK 9` から削除されたため、`gradle-jooq-plugin` のバージョンを `3.0.2` に更新。

## Java 11 へ更新

やったことは以下のような感じです。

- OpenJDK 11 をインストール https://qiita.com/spaciba_h_t/items/c96e96be99596b0a9fe4
- IntelliJ IDEA の project structure を開いて JDK 11 に変更

が、`gradle build` でエラーが発生。

https://intellij-support.jetbrains.com/hc/en-us/community/posts/360000615010-IntelliJ-is-adding-a-no-longer-supported-Djava-endorsed-dirs-JDK-9-parameter-on-Gradle-runs-which-results-in-failure

`build.gradle` に以下を追記して解決。

```
bootRun {
    systemProperties.remove("java.endorsed.dirs")
}
```
`gradle build` は成功するようになったが、SSL 証明書がらみで警告が出る。
調べたところ、`JDK 12` では修正済みだが `JDK 11` は修正中で、`11.0.2` リリース時に解消されるとのこと。2019年1月予定？ 

https://stackoverflow.com/questions/52016415/jdk-11-ssl-error-on-valid-certificate-working-in-previous-versions

## まとめ
トータル2時間弱で更新できた。500ケース近くある JUnit が1つも落ちなかったので良かった。
今後もバージョンアップ頑張ります💪
DI:Dependency Injection(依存性注入)ってなに?

##本ページの目的
色々な解説を見てもしっくりこない為自分を納得させるために書く。

##DIの概要
まずは教科書的な書き方だと
>「DIはデザインパターン[^1]の一つである"Inversion of Control Principle"(制御の反転の原則)」を実現する。
　コンポーネントを構成するインスタンスの生成と依存関係の解決をソースコードから分離することが出来る。
(Spring徹底入門より　株式会社NTTデータ著)

何を言っているのかわからないですね。
とりあえず理解しやすいところから考えるようにしましょう。

[^1]: オブジェクト指向の言語での設計ノウハウ集

##DIのメリット

とりあえず何をどうするかは置いといて、DIによってなにが良くなるのかというと

・クラス間の依存性が下がる = クラス間の結合が疎になる(疎結合になる)
・↑によってクラスなどの再利用が簡単になる
・↑によって単体テストなどがやりやすくなる

という事らしいです。
なにやら依存性という言葉が何度も出ているため、ここに核心がありそうです。
ではプログラミングにおける「依存性」とはなんなのでしょうか？


##依存性とは
こちらも教科書的な言葉を使うと、
「あるモジュールが別のモジュールの内部動作によって変化したり依存したりする = 依存関係にあるモジュールの仕様を変更した場合、モジュールの内容が壊れる可能性が大きい」

実際にJava言語などで依存性が高い構成とは
・あるクラスのメソッド内で別のクラスのインスタンスをnewして生成している
・あるクラスのメソッドの引数として他のクラスのインスタンスを使用している
といったものが挙げられます。
具体的なコードだと


```java:Hoge.java
class Hoge{
    public void hoge(){
        Fuga fuga = new Fuga();
    }
}
```

かなり具体的になってきましたね。
あるクラスで他のクラスをnewして使用した場合、newするクラスのコンストラクタなどの変更あった場合、呼び出し元のメソッドも変更しなければいけないことは想像できると思います。
そのほかにもインスタンスを生成するクラス内でメソッドを変更した場合も呼び出し元の処理がぐちゃぐちゃになってしまいます。
この問題の解決方法としては、呼び出し元のクラスでは、実装クラスをnewしてインスタンスを生成するのではなく、インターフェイスを利用するようにして、実際にnewするクラスはインターフェイスを継承したクラスにする、というものです。

```java:Fuga.java
pulic interface Fuga{
    int a;
    void foo();
}
```
```java:HogeFuga.java
pulic HogeFuga implements Fuga{
    int a;
    void foo(){
        fugafuga;
    };
}
```


```java:Hoge.java
class Hoge{
    public void hoge(){
        Fuga fuga = new HogeFuga();
    }
}
```

この方法を用いることで、インターフェイスをimplementしたクラスを自由に使用できるようになるため、依存関係を低下させることが出来ます。
しかし、結局インターフェイスクラスはnewすることはできない為、implementしたサブクラスを呼び出し元でnewする記述が必要です。

そこで、その関係性をxmlファイルやアノテーションを用いて記述する
↓
これが「DI」

##具体的なDIの方法
####セッターインジェクション

```java:Hoge.java
class Hoge{
    Fuga fuga;
    public void hoge(){
    }
    public void setFuga(Fuga fuga){
         this.fuga = fuga;
    }
}
```

この時、setFugaクラスに渡すのはFugaクラスをimplementしたクラスであればなんでも良く、Hogeクラスは実際にどのクラスを使用しているかは関知しない。

####アノテーションインジェクション

Springを使うとこちらの方が主流でしょうか

```java:Hoge.java
class Hoge{
    @Autowired
    protected Fuga fuga
    public void hoge(){
    }
}
```

##まとめ
DIってなに？　＝　使用するクラスの縛りを減らしたい！
プログラミング言語ごとのコメントアウトの記法まとめたら便利じゃね？って話


プログラミング言語ごとのコメントアウトの記法まとめ

11/7微修正
#C言語 / C++


```comment.c
// 単一行コメント
/*
  複数行コメント
  複数行コメント
*/
```
#Python
```comment.py
# 単一行コメント
#　下記の記法で複数行コメントアウトできるが書く場所によっては文字列として残る場合がある
'''
複数行コメント
複数行コメント
'''
```
#Java
```comment.java
// 単一行コメント
/*
  複数行コメント
  複数行コメント
*/
```

#Ruby
```comment.rb
# 単一行コメント
=begin
  複数行コメント
  複数行コメント
=end
```
#Go
```comment.go
// 単一行コメント
/*
  複数行コメント
  複数行コメント
*/
```
#R
```comment.r
#　単一行コメント
#　単一行コメントしかできないが以下で擬似的に複数行のコメントするようにできる
if(0){
 複数行コメント
 複数行コメント
}
```
#シェルスクリプト
```comment.sh
# 単一行コメント
```
#Perl
```comment.pl
# 単一行コメント
=comment
  複数行コメント
  複数行コメント
=cut
```

#HTML5
```comment.html
<!--コメントは単数でも複数でもできる-->
```
#JavaScript
```comment.js
// 単一行コメント
/*
  複数行コメント
  複数行コメント
*/
```

#CSS
```comment.css
/*
  複数行コメント
  複数行コメント
  単一行コメント用の記法はない
*/
```

とりあえず使用頻度の高そうな言語についてまとめた。
もし間違ってたり足して欲しいものがあったら言ってほしいナリ。
MacにOpenCVを導入する

## 動作環境
| 項目 |   内容  |
|:------------:|:------------:|
| OS |     OS X El Capitan     |
| OpenCV |   2.4.13.1    |
| Python |   2.7.10    |

## 環境構築

* OpenCVのインストール

```sh
$ brew update
$ brew install -v cmake
$ brew tap homebrew/science
$ brew install opencv
```

* 環境変数の設定

```sh
export PYTHONPATH="/usr/local/lib/python2.7/site-packages/:$PYTHONPATH"
```

* 動作確認

```sh
$ python
>>> import cv2
>>> cv2.__version__
'2.4.13.1'
```

## サンプルコード
Pythonのサンプル(Canny法によるエッジ検出)を動かす

```python
import cv2
 
src_img = cv2.imread('Lenna.png')
canny_img = cv2.Canny(src_img,100,200)

cv2.imshow('src',src_img) 
cv2.imshow('canny',canny_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

## 実行結果  
左が入力画像で、右がCanny法によるエッジ検出の結果。  
![opencv_sample_001.png](https://qiita-image-store.s3.amazonaws.com/0/134341/6ab6f9b7-6985-7a0e-c7c9-0a72da71167a.png)



## 参考記事
RubyとOpenCVで始める画像処理
https://techblog.gmo-ap.jp/2016/11/28/ruby%E3%81%A8opencv%E3%81%A7%E5%A7%8B%E3%82%81%E3%82%8B%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86/
デベロッパー向けスマホ・タブレット情報サイト

業務中に見つけた便利そうなサイトのメモ。

[スマタブinfo by KSK](http://smatabinfo.jp/index.html)
>スマタブinfoとは、機種情報×バグ情報がまとめて見つかる開発者向けスマホ・タブレット情報サイトです

現時点では、古い機種で使われてるCPUアーキテクチャを調べるぐらいしか用途が思いつかない。
日本固有の機種をカバーしていること、バグ情報の共有サービスを準備中ということから今後有効に利用できそうだと思いました。

プリインストールアプリのアプリ名やパッケージ名が閲覧できたら自分の業務に有効活用できそうだけど、ここら辺はベンダから情報が公開されてるケースが僅かなので望み薄。
Safari 12ではユーザがインストールしたフォントをfont-familyに指定できない

## 背景

個人的にはMyriadが好きなので、自分用に作ったサイトとかではよく「Myriadがインストールされている人（主に自分）だけにMyriadで表示されればいいやー」と思って以下のようにCSSを書いていたんだけど、macOSをMojaveにしたあたりからMyriadで表示されずLucida Grandeになってしまった。

```css
font-family: "Myriad Pro", "Lucida Grande", sans-serif
```

## 解決

Mojave (Safari 12) からは、システムフォントだけしか指定できなくなってしまったらしい。なんでもユーザートラッキングを防ぐためだという。なので解決策としては、Webフォントにする、あるいはChromeを使う（ちがう）。

[Font Family/Display Issue in Safari 12 on macOS Mojave - Stack Overflow](https://stackoverflow.com/questions/52692905/font-family-display-issue-in-safari-12-on-macos-mojave): 

> This is because of the new no-tracking privacy features in Safari 12 + Mojave.   
> Web developers **no longer have access to the ‘traditional web-safe fonts’**; only the strict set of System fonts included in /System/Library/Fonts ‘from the factory’

[Myles C. Maxfield on Twitter](https://twitter.com/Litherum/status/1051858854705651712) (AppleのWebKitチームの人) : 

> Safari now disables user-installed fonts in an effort to reduce fingerprinting across the web. Trackers can detect which fonts you have installed and use that info to track you across totally different websites, even into private browsing mode. We fixed it in Mojave.
NimとC言語の連携

https://qiita.com/snowlt23/items/1696687cca61bfedb1cc で取り上げられていた内容の拡張といった感じ。

ご存知の通り、Nimはいろんな言語との連携が可能です。
今回紹介するのは主にCとNimとで関数を共有する方法です。

注意 : 
・コンパイル時「test.nim」の「.nim」は省略可能ですがあえて残しています。

# C言語の関数をNimで利用

## ファイルから宣言

**Cのコードのほうの拡張子は「.h」でもOKです。**
### 一つずつ宣言する
```c:test.c

int dfunc(int b){
    return b-1; // 引数に1を引いた数を返す
}

int cfunc(int a){
    return a*2; // 引数に2を掛けた数を返す
}
```
この`dfunc`と`cfunc`をNimで使ってみましょう。

```nim:test.nim
# 宣言
proc function(a:cint):cint{.header:"［CFILE」",importc:"dfunc".}
# 「CFILE」にtest.cのパスを入れる<<絶対パス、またはnimcacheからの相対パス>>
#  例 : {.header:"C:/Code/test.c",importc:"関数名".}

proc cfunc(a:cint):cint{.header:"「CFILE」".}
#  同じ関数名の場合はimportcが省略できる(ここでは{.importc:"cfunc".}が適用される)


echo function(12)
echo cfunc(12)

# ここでは 12
```
で、`test.nim`をビルドします。

```console:console
> nim c -r test.nim
11
24
```

### ファイルごとにまとめて宣言
push - pop を使うことによりheaderプラグマを省略しています。

```nim:test.nim
# 宣言

{.push header:"../test.c".}  # header : ... を省略する

proc function(a:cint):cint{.importc:"dfunc".}
proc cfunc(a:cint):cint
# 関数の中身はさっきと同じ

{.pop.}

echo function(12)
echo cfunc(12)
# 出力もさっきと同じ

```

## ライブラリから宣言

ここでは、Cのファイルは使用しません。
ライブラリから直接関数を持っていきます。

```nim:test.nim
{.push header:"<stdio.h>".} # 標準ライブラリ"stdio.h"

proc printf(a:cstring,b:auto) # {.header:"<stdio.h>".}
proc scanf(x:cstring,y:auto)

{.pop.}

var n:char

scanf("%c",n.addr)
printf("Hi, I am C Library!\ncharacter:%c",n)
```
これで、C言語で使った時とと同じ挙動が再現されます。

```console:console
> nim c -r test.nim
> t
Hi, I am C Library!
character:t
```

# Nimの関数をCで利用
ちょっと手間がいります。

```test.nim
proc nitest(a:int):int {.exportc.}=
    return a+8 # 引数に8を足した数を返す

# exportc プラグマを忘れずに！
```
これを、次のようにビルドします。

```console:console
> nim c --noMain --noLinking --header:test.h test.nim
```
( test.hのところをtest.c と書いても同じ結果です )

すると、nimcacheに`test.h`という名前のファイルが生成されたはずです。
これをCに使わせます。

```c:test.c
#include "test.h"
#include <stdio.h>

int main(){
    NimMain();
    printf("%d\n",nitest(7)); //ここでは例として 7
}
```

これを、

```console:console
 > gcc -o test.exe -Inimcache -I"「LibPATH」" nimcache/*.c test.c
```
**LibPATH**には、Nimのコンパイラのlibファイルのパスを入れてください。
これでコンパイルできるはずです。

```console:console
> ./test.exe
15
```

# 最後に
もう気づけば真冬ですね。
冬はこたつでNimやろうぜ