OmniAICreator/Qiita-1.07M huggingface dataset:
AndroidX に migrate する

# 概要

放置されているアプリを AndroidX 対応したときの手順メモです。
困ることもなくすんなり終わったので大したこと書いてませんがご参考までに。

※ Android Studio 3.2 以上が必要です。

[コチラに公式手順](https://developer.android.com/jetpack/androidx/migrate) があります。

# 環境
macOS Catalina - 10.15.1
Android Studio - 3.5.2

# 手順

- Android Studio のメニューから Refactor - Migrate to AndroidX

![スクリーンショット 2019-12-11 15.57.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34926/49f5529d-99d2-ea01-d79a-c715e15ad20f.png)

- 確認ダイアログと、現状をバックアップするか聞かれるので一応チェック入れた状態で Migrate

![スクリーンショット 2019-12-11 15.57.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34926/ab98cf98-d352-20ae-f074-3ab96a77c0a7.png)

- バックアップのファイル名を聞かれるので入力して Save

![スクリーンショット 2019-12-11 15.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34926/37c2c7cd-c8fe-e00f-e11d-d1f6ae823fdb.png)

- migrate 対象の箇所がズラッと表示されるので対象ファイルを確認して Do Refactor

<img width="653" alt="スクリーンショット 2019-12-11 16.03.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34926/89366565-8fe4-50ed-9ad4-9eefbf643d1f.png">

- migrate が完了したら実行してみる

- 以下のエラーがでた

```
The given artifact contains a string literal with a package reference 'android.support.v4.content' that cannot be safely rewritten. Libraries using reflection such as annotation processors need to be updated manually to add support for androidx.
```

- ググると [ButterKnife](https://jakewharton.github.io/butterknife/) が古いせいのようだったのでバージョンアップ

```diff
-    implementation 'com.jakewharton:butterknife:9.0.0'
-    annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0'
+    implementation 'com.jakewharton:butterknife:10.0.0'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0'
```

- もう一度実行してみたら動いたので完了

# 補足

「Do Refactor」 をすると gradle.properties に以下の2行が追加される

```
android.useAndroidX=true
android.enableJetifier=true
```

作業中なにか割り込みが入るなどして前の状態にしたいときはこの2行も消す必要があります。

# 参考
[The given artifact contains a string literal with a package reference 'android.support.v4.content' that cannot be safely rewritten. for androidx](https://stackoverflow.com/questions/53484988/the-given-artifact-contains-a-string-literal-with-a-package-reference-android-s)
GCP Cloud KMS使って、セキュリティーデータファイルを暗号化

実施手順のまとめ

- キーリングおよび暗号鍵の作成
- KMSの暗号鍵で秘密ファイルを暗号化する
- 秘密ファイルを利用する際、暗号鍵で復号化する

## キーリングおよび暗号鍵の作成
Cloud Build で SSH 認証鍵を使用するには、Cloud KMS CryptoKey を使用して鍵を暗号化、復号する必要があります。CryptoKey は KeyRing オブジェクトに格納されます。

KeyRing と CryptoKey を作成するには、gcloud kms keyrings create および gcloud kms keys create コマンドを使用します。

KeyRing を作成するには、shell またはターミナル ウィンドウで次のコマンドを実行します。このチュートリアルでは、KeyRing my-private-keyring に名前を付けます。

```sh
# Create a Cloud KMS KeyRing
gcloud kms keyrings create my-private-keyring --location=global
```

コンソール画面で作成結果確認
<img width="887" alt="gcp_kms_001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535707/c33ba259-e6d4-7031-7286-ac831aa1a0e6.png">

次に、my-private-key という CryptoKey を作成します。このコマンドは、my-private-keyring KeyRing に my-private-key CryptoKey を作成します。

```sh
# create a CryptoKey 
gcloud kms keys create my-private-key --location=global --keyring=my-private-keyring --purpose=encryption
```

コンソール画面で作成結果確認
<img width="1195" alt="gcp_kms_002.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535707/aaa7a9e2-5059-47f9-300f-d2f7ffc20bab.png">


## KMSの暗号鍵で秘密ファイルを暗号化する
秘密ファイルがあります。

```sh:my_secret.txt
I'm falling in love with Aosora
```

これは見られたら大変なので暗号化をします。
暗号化するには、gcloud kms encrypt コマンドを使用します。

次のコマンドを実行します。正しいパスを指定してください。

```sh
# Encrypt a secret
gcloud kms encrypt --plaintext-file=/full/path/to/my_secret.txt \
--ciphertext-file=/full/path/to/output/my_secret.txt.enc   \
--location=global --keyring=my-private-keyring --key=my-private-key

# 暗号化された内容を見てみる
cat my_secret.txt.enc 
>
>$u?ڤS??f?C???r??`?p@??4 ?e???I???}??:x&]g???c??C[&??ܡ~l|??o????t?z??/?8?
>                                                                        x	W?C_:? b??Q????Xw?m#?

# 秘密を暗号化しましたので、生データを削除します。
rm my_secret.txt
```

暗号化（encrypt）するため、'cloudkms.cryptoKeyVersions.useToEncrypt'権限を持つアカウントで実施する必要です。
通常ProjectのEditorでも、この権限はありません。
Ownerアカウントで実施するか、この権限を個別で追加するかという対策は必要です。


## 秘密ファイルを利用する際、暗号鍵で復号化する

```sh
# Decrypt a secret
gcloud kms decrypt --ciphertext-file=/full/path/to/my_secret.txt.enc \
--plaintext-file=/full/path/to/output/my_secret.txt \
--location=global --keyring=my-private-keyring --key=my-private-key
```

復号化（decrypt）するため、'cloudkms.cryptoKeyVersions.useToDecrypt'権限を持つアカウントで実施する必要です。
通常ProjectのEditorでも、この権限はありません。
Ownerアカウントで実施するか、この権限を個別で追加するかという対策は必要です。


<br>
ご覧して頂き、どうも有難う御座います!
DSS Ben
GitのaliasでPermissionエラーが出るときの対応

Gitのaliasで以下のようにエラーが出るとき

```
[user@dev $ git co -b hoge
fatal: cannot exec 'git-co': Permission denied
```

userユーザーになるときに `su user` にしてしまったのが原因
`su - user`ってすればよい
Curlコマンドの使用

API試験時に実行方法としてCurlコマンドを使用したので、まとめてみました

*Curlコマンドとは*
サーバもしくはサーバへデータ転送を行うコマンド

*CurlのGetコマンド*
　-s　　転送情報の表示を省略する
　-Ss　 error情報があれば表示
　-v　　  header情報も表示

　APIのGetを実行
　$ curl -X GET https://xxxxxxx.xxxxxxxx.com/api/　


*CurlのPostコマンド*　
-X POST POSTを叩くURLを指定
-d　　　bodyを付与
-H 　　headerを付与

APIのPostを実行
-X POST -d 'リクエスト'　https://xxxxxxx.xxxxxxxx.com/api/
画像アップロード時に「Missing required arguments: aws_access_key_id, aws_secret_access_key」エラーが発生する

プログラミングスクールのカリキュラムでメルカリのクローンサイトを開発中、商品の画像をデータベースに保存しようとしたところ、タイトルのエラーが発生。

検索しても、該当する記事が見当たらなかったので記事にしました。

エラー画面がこちらです。
<img width="1440" alt="スクリーンショット 2019-12-11 16.05.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528941/34cc95f6-3713-da5c-a1b9-739a2c51d16b.png">


ローカルで画像を保存しようとしてるだけだし、AWSとか関係ないだろーと思って解決方法を模索していましたが、辿り着いた答えは単純でした。
画像をアップロードするためにCarrierWaveを使用していたのですが、「image_uploader.rb」の記述に問題がありました。


## エラーの原因

```image_uploader.rb
  # Choose what kind of storage to use for this uploader:
  # storage :file
  storage :fog
```
storage :fogが適用されているせいでCarrierWaveの保存先がS3になっていました。



## 解決方法
storage :fogをコメントアウトしてあげて、storage :fileのコメントアウトを解除してあげればエラーが無事解決します。

```image_uploader.rb
  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog
```

## 補足
ローカルでの作業後、CarrierWaveの保存先をS3に戻す場合は逆の修正を行えば簡単に戻せます。
エンジニアの組織と役職とオフィサー

------------
## はじめに
<p>本投稿はエンジニアの組織と役職とオフィサーについて、つらつらと書き連ねる記事である。</p>
書面に書かれていることがすべて、契約をベースに社会が成り立っている契約社会のアメリカでは、詳細に各役員や従業員の役割を定義して契約としてまとめる必要があり、その結果従来よりCEOやCOO,CFOという役割ベースのボードメンバー体制や～マネージャといった細分化された役割に対して固有の名称が与えられており業務の役割が多様化すればその分だけ役職が作成され、それぞれの分野のスペシャリストになることが求められた。

一方、日本の多くの組織では特に役割は定義されず、専務や常務、部長や課長といったようにヒエラルキーの中の序列を定義する強い意味合いの中で配置され、組織内で必要とされる業務を自分のスキルの幅を広げ積極的に巻き取っていくことが評価される等、役職を遂行する者にはジェネラリストとなることが求められた。

ただ昨今その流れも変わり、インターネットが生活インフラとなることに伴い、マーケティングの役割を一つとってもブランディング,ウェブプレゼンス,ソーシャルメディアプレゼンス,ユーザとのタッチポイントの方法等多岐にわたり、従来型の組織慣習である個人がスキルの幅を広げて必要とされる業務を遂行することが難しくなった背景があり、日本の企業でもCMOやCBDOやブランディング部長といったように役割ベースでの役職の定義をする企業が爆裂的に増えてきている。

そのなかで、現代の職人や大工といわれるエンジニアに関わる役職についても、役割ベースを基本に変化してきている。


## オフィサー
エンジニアに関する話の本題に入る前に、どんなオフィサーが存在するか調べてみた

基本的なところだと

#### CEO
会社組織全体の方向性や経営資源の配分等を決定する

#### COO
CEOが立案した企業戦略にももとづいて、会社全体でどう業務を遂行し企業戦略を達成するかについて
目の前の業務に落とし込み運用することに決定権を持つ

#### CFO
会社全体の財務計画や経済資源に対して決定権を持つ

#### CMO
会社全体のマーケティング戦略に対して、最も大きな権限を持つ
ただしマーケティング活動の範囲が莫大なので、徐々にマーケティングからブランディングだけを
切り分けて別のオフィサーを立てる等分派がすすんでいる

#### CTO
会社全体の技術戦略や研究開発投資について大きな権限をもつ

#### CIO
CTOが作り上げた技術的な武器をどうIT全体戦略として活用するか、経営とITの両側面を勘案して
会社のIT戦略に対して大きな決定権をもつ


これ以外にも下記の通り、様々オフィサーが存在する

#### CISO
セキュリティに対する重要性が高まる中で、情報セキュリティをどう確保するかについてのセキュリティ戦略に対して
責任を負う

#### CPO
個人情報を正しく保存しているかおよびユーザに対しての個人情報の使い方の明示及び許可の方法等の個人情報に
関連する部分で責任をもつ

#### CBDO
ビジネス開発についての戦略に対して責任をもつビジネスに関連する知識(リサーチ,パートナーアライアンス,マーケティング)を集約し
新規ビジネスや既存ビジネスのグロースを図る

#### CBO
会社のレピュテーションやウェブでの自社ブランドのブランディングを初めとして、どうユーザやステークホルダーから
評価されるかという所のブランディング戦略に責任を持つ

#### CKO
会社に散在する知識やノウハウから顧客情報等を収集、管理、可視化し企業活動の効率最大化を図る
知識の中には従業員の強みや弱み、モチベーションや従業員同士の関連性等も含まれる

#### CLO
企業活動のなかでリーガルの観点から、法に抵触する部分はないか企業法務の最高権限を保有する

## エンジニアと役職
終身雇用の概念が薄れ雇用の安定が過去の神話となった現代の労働状況において、会社に帰属して貢献することの見返りが低下し、従業員の会社への忠誠心も同時に低くなっている。
また一人一人の個人が競争力を維持して安定雇用を実現する必要がでており、会社の業務を通して自分自身の市場価値を上げられるかどうかが従業員の労働意欲にダイレクトに結びついている。

エンジニアにとって多くの場合、自分自身の市場価値はエンジニアスキルであり、各メンバーの市場価値向上と企業活動の最大化を結びつける役目が必要となってきており、"VPoE"という役割が生まれている。

現代の職人や大工といわれるエンジニアは、自分自身の中にこだわりがつよい。
コーディングを一つとってもモジュールの粒度はこうあるべきだ等、個人の意見をしっかりもっており尚且つエンジニアリングやコーディングに絶対的に決まった答えはないので、ある視点を切り取ってみるとその主張には正しさがある。

だからこそ、どの視点や方向性が会社として正しいのか技術的に決定する必要があり、CTOがその役目を果たしている。

組織や人事面で、採用及びエンジニアの市場価値と企業活動を結びつけて生産性を向上させるための評価制度や、今いる人材が能力を発揮してポテンシャルを伸ばしていける組織文化や教育体系、また現在あるor将来そう持っていきたい組織文化と、フィットするかどうか見極める人事採用等の技術部分以外で方向性や視点を決定するのが"VPoE"である。

こういった役職が生まれた背景を推察すると、エンジニア組織の難しさとともにエンジニアのビジネスにおける価値の高さを推察できる。

##　さいごに
管理する役割として、各メンバーの価値と会社のビジネスのグロースを結びつけるという仕事は予想以上に労力を費やす職務であり、様々な人と意見交換をさせていただく機会のなかで、やはり多くの人が悩み、試行錯誤を繰り返しながら改善し運用しており、今後も時代共にエンジニアの組織は劇的な変化を迎えるなかで、都度都度アダプティブに対応していかなければならない重要な役割である。


明日の記事は@niku_motoさんです。
よろしくお願いします。
manylinux wheelのビルドにcircleciを使わせていただいている話

# manylinux wheelとは

manylinuxという「大体すべてのLinuxディストリで動く」wheelがあります。
wheelというのはコンパイル済みのネイティブライブラリを含むPythonパッケージです。
有名どころではtensorflowがこのmanylinux wheelを配布していたりします。
このmanylinux wheelのビルドにcircleciが最適だったので紹介します。


# なぜ manylinux wheel の作成に circleciが適しているか

- CIサービス内でArtifact(私の場合wheel)の保存ができる

ため私はcircleciでmanylinux wheelのビルドを行っています。

具体的には https://github.com/ecell/ecell4_base/blob/master/.circleci/config.yml のように行っています。

yml中では

```
- store_artifacts:
  path: /root/circle/wheelhouse
```

がそれを行っている箇所になります。
私が知る限りtravisci **内** ではこれを行うことができずcircleciを使わせていただいている次第です。


manylinuxのwheelは「大体すべてのLinuxで動く」というものなので
この環境中での動作テストだけでは不十分で他の複数のディストリでの動作も見たかったりします。

```
docker:
  - image: quay.io/pypa/manylinux2010_x86_64
```

はCentOS6です。(なぜそんな古いバージョンなのかはここでは割愛します。)

なのでとりあえずパッケージを置いておく場所がほしかったりします。
そこでこのArtifactの保存の機能が助かるんですね。

# おわりに

昨日 [【大阪】CircleCI ユーザーコミュニティミートアップ#2](https://circleci.connpass.com/event/148274/) でCircleCI Japanコミュニティの皆様にお世話になり本記事を書きたいと思うに至りました。
コミュニティって重要ですね。

以上。
[ Postgre ]　Postgreとは

##Postgresとは
リレーショナルデータベースの操作ができるオープンソースのデータベース管理システム。
通称「ポスグレ」。インストールなどは以下を参照して頂きたい。

日本PostgeSQLユーザ会
https://www.postgresql.jp/download
インストール方法
https://eng-entrance.com/postgresql-download-install

webで使われるデータベースで人気が高いのはMySQLで、それを嫌いない人はPostgreを選ぶらしい。
https://wa3.i-3-i.info/word11777.html

##JDBCとは
リレーショナルデータベースにアクセスするために必要となる標準Java APIである。
JavaでPostgreを使うには必須である。
テスト環境におけるDockerコンテナ間のHTTPS通信

この記事はZOZOテクノロジーズ #1 Advent Calendar 2019 17日目の記事になります。
昨日の記事は @pakio さんによる「[非ElasticsearchユーザーにもおススメなKibanaで地味に便利な機能を紹介したい](https://qiita.com/pakio/items/7cb2d6329c5dad861fa9)」でした。

本記事では、Dockerのコンテナ間でHTTPS通信をするテストを実装した際に困ったことの解決方法を紹介します。

# 概要
テスト環境に対してHTTPS通信を行うために自己証明書（いわゆるオレオレ証明書）を使う場合、基本的に警告が出るので明示的に通信を許可する必要があります。
SeleniumやPuppeteerなどを使っている場合は、証明書に関するエラーを無視するようなオプションを設定することで、この状況を回避できますが、内部でHTTPS通信を行うライブラリによっては、そのようなオプションが用意されていない場合もあります。
Dockerのコンテナ間でHTTPS通信する際にそういった状況に遭遇した場合の解決方法を紹介していきます。

# 環境
- macOS High Sierra (v10.13.6)
- mkcert (v1.4.0)
- docker desktop (v2.1.0.4)

# 解決方法の概要
オレオレ証明書の代わりにオレオレ認証局を作り、その認証局をアクセス元のコンテナで信用するようにします。

![解決方法のイメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54957/3adb67aa-77c1-a2c1-d32c-38c5f2bfbf84.png)

1. ホストマシン上に認証局を作成
2. 認証局からコンテナB用のSSLサーバー証明書を発行
3. 認証局のルート証明書をコンテナAが持つルート証明書一覧に追加
4. 発行されたサーバー証明書をコンテナBで利用
5. コンテナAからコンテナBにHTTPSアクセス

# サンプルコード
本記事で紹介する例とは多少異なりますが、SSLサーバー証明書を利用したNginxにPuppeteerでアクセスする場合の[サンプルコード](https://github.com/AmatsukiKu/containers-https-access-sample)を上げているので、こちらも必要に応じてご参照ください。

# 詳細手順
## 認証局の作成
[mkcert](https://github.com/FiloSottile/mkcert)を使うと簡単に認証局を作成できます。

```sh
mkcert -install
```

## SSLサーバー証明書の発行
続いて、mkcertを使って認証局からSSLサーバー証明書を発行します。

```sh
mkcert container-b
```

このコマンドでは、証明するホスト名を指定する必要があるので、コンテナAから見たコンテナBのホスト名を指定します。

## ルート証明書のエクスポート
![キーチェーンアクセス上のルート証明書](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54957/4751d37e-e46d-c7e6-454f-7f6d8602eec2.png)

キーチェーンアクセスからmkcertによって作られた認証局のルート証明書を探し、メニューバーの「ファイル」→「書き出す」で保存します。
この記事では `local-root-ca.pem` というファイル名で保存しています。

## ルート証明書の追加
```Dockerfile:Dockerfile
...
COPY local-root-ca.pem /usr/local/share/ca-certificates/local-root-ca.crt
RUN update-ca-certificates
...
```

エクスポートしたルート証明書をコンテナAのルート証明書一覧が管理されているディレクトリ下に配置し、一覧情報を更新します。

＊ 証明書一覧が管理されているディレクトリや、更新のコマンドはOSによって異なります。上のはDebianの場合です。

## SSLサーバー証明書の利用
構成によって変わるので、割愛します。

## コンテナAからコンテナBへのHTTPSアクセス
```Dockerfile:Dockerfile
CMD curl https://container-b/
```

`-k`や`--insecure`のオプションを付けなくてもエラーが出ないことを確認します。

# 最後に
オレオレ認証局を作成して発行したSSLサーバー証明書を利用することで、コンテナ間のHTTPS通信を警告なしに行うことができるようになりました。開発環境やテスト環境でお困りの際にはぜひご活用ください。

明日の記事は、 @katsuyan さんによる「Googleスプレッドシートの縦横変換をSQLでおこなう」です。そちらもぜひご覧下さい。

# 余談
JRE (Java Runtime Environment)といった環境やライブラリによってはルート証明書一覧が同梱されており、OS側のルート証明書一覧を参照しないという場合もあります。
こういった場合には、ルート証明書追加の手順で行ったような操作では意味がないため、ライブラリ等に同梱されたルート証明書一覧に追加する方法や、OS側のルート証明書一覧を見るように処理を上書きする方法を考える必要があります。
Dockerコンテナ内で起きたcore dumpをデバッグ

## 前置き
自作したプログラムがコンテナの中でセグフォを起こした...そんな経験はありませんか？
コンテナ内部のcoredumpctlにはデバッグ情報が残りません．
またコンテナに特権を与えなかった場合，/proc以下のファイルはコンテナ側で操作することができず，coreファイルの出力設定も変更ができません．
そこで今回はそんな環境下でもコンテナ内部で発生したcore dumpをデバッグする手法を公開します．

## やり方
結論は非常に簡単で，__ホスト側のcoredumpctlにデバッグ情報が保存__されています．
そこでホスト側のcoredumpctlを使い，コンテナから(ヴォリュームマウントなどで)取り出した実行ファイルと合わせてデバッグすればOKです．
※ coredumpctlを使わずにcoreファイルが直接吐き出される場合は，落ちたコンテナをcommitして作ったイメージをrunして中でデバッグすればOKです．

バイナリデータの取得は[`docker cp`コマンド](https://docs.docker.com/engine/reference/commandline/cp/)を使ってください．

## 何故ホスト側のcoredumpctlにデバッグ情報が？

同じようにコンテナ側でcoredumpctlがお仕事をしてくれない件が[issue](https://github.com/coreos/bugs/issues/371)として出ていました．
その中でcatrixs氏が「Because coredump is captured by kernel」と指摘しています．

## 実験

### 実験環境

|  環境  |  名前  |
| ---- | ---- |
|  OS  |  Manjaro 18.1.3 Juhraya  |
|  Dockerクライアント  |  19.03.4-ce  |
|  Cコンパイラ | gcc 9.2.0 |
|  デバッガ | gdb 8.3.1 |

### 手順
以下のように`segfo_sample.c`を作成します．

```c
#include<stdio.h>

int main() {
  char* null_po = NULL;
  printf("%d", *null_po);
}
```
コンパイルした実行ファイルをコンテナにマウントして実行しましょう．

```sh
$ gcc -g segfo_sample.c -o segfo_sample
$ docker run --rm -it -v ${PWD}/segfo_sample:/root/segfo_sample -w /root debian bash
root@f36b0603fce1:~#  ./segfo_sample
Segmentation fault (core dumped)
root@f36b0603fce1:~#　exit
```
コンテナを抜け，ホスト側でコアダンプ情報を確認しましょう．

```sh
$ coredumpctl info segfo_sample
           PID: 31371 (segfo_sample)
           UID: 0 (root)
           GID: 0 (root)
        Signal: 11 (SEGV)
     Timestamp: Wed 2019-12-11 15:10:30 JST (25s ago)
  Command Line: ./segfo_sample
    Executable: /root/segfo_sample
 Control Group: /system.slice/docker.service
          Unit: docker.service
         Slice: system.slice
       Boot ID: 6890bb7e1fbf4346af58a455e5087c1c
    Machine ID: 4ea99d5d328042c1985355191e83ab72
      Hostname: cabon
       Storage: /var/lib/systemd/coredump/core.segfo_sample.0.6890bb7e1fbf4346af58a455e5087c1c.31371.1576044630000000.lz4 (inaccessible)
       Message: Process 31371 (segfo_sample) of user 0 dumped core.
                
                Stack trace of thread 7:
                #0  0x000055feb6c0f14d n/a (/root/segfo_sample)
                #1  0x00007f05571f12e1 n/a (/lib/x86_64-linux-gnu/libc-2.24.so)

```

ちゃんとホスト側に情報が来ているので，PIDを指定してデバッグしちゃいましょう．

```sh
$ sudo coredumpctl debug 31371
[sudo] password for takahiro: 
           PID: 31371 (segfo_sample)
           UID: 0 (root)
           GID: 0 (root)
        Signal: 11 (SEGV)
     Timestamp: Wed 2019-12-11 15:10:30 JST (2min 12s ago)
...
/root/segfo_sample: No such file or directory.
[New LWP 7]
Core was generated by `./segfo_sample'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000055feb6c0f14d in ?? ()
(gdb)
```
あらら...`/root/segfo_sample`なんて実行ファイルが無いから覗けないよ？って言われてしまいましたね...コンテナとはパスが違うので当然といえば当然ですが...
fileコマンドを使って，ホスト側に残された実行ファイルを指定しましょう．

```sh
(gdb) file segfo_sample 
Reading symbols from segfo_sample...
(gdb) run
Starting program: /home/takahiro/hoge/segfo_sample 

Program received signal SIGSEGV, Segmentation fault.
0x000055555555514d in main () at sample.c:5
5	  printf("%d", *null_po);
(gdb)  backtrace
#0  0x000055555555514d in main () at sample.c:5
```
いい感じです．
INSTALL_REFERRERが廃止されるというお話

# ソース

https://android-developers.googleblog.com/2019/11/still-using-installbroadcast-switch-to.html

2020年3月1日から、PlayストアがINSTALL_REFERRERブロードキャストインテントを投げなくなる、ということのようです。

# 調査どころ

## 1. 広告SDK、計測系SDKを使っているか？

大抵のSDKは、[Play Install Referrer API](https://developer.android.com/google/play/installreferrer/library.html)への移行が済んでいるようなので、最新版にアップデートし、各社のマイグレーション手順に従いましょう。（大手のSDKがこの移行が完了したので、停止をアナウンスできるようになったようです）

## 2. マニフェストファイルの確認

マニフェストファイルに下記の記述があるか確認。

```AndroidManifest.xml
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER"/>
            </intent-filter>
```

他社製SDK等で使っている以外で、上記記述があるのであれば、[Play Install Referrer API](https://developer.android.com/google/play/installreferrer/library.html)に移行する。

自社製ライブラリなどでもよく調査して下さい。

## 3. GA/FAを使っている場合

現在、
「これらのアプリがINSTALL_REFERRERを使っているからAPIに変えてね」
と警告するメールが適宜Googleより届いているようです。

で、このアプリの抽出が、どうやら、

**"INSTALL_REFERRER"**だけをgrepかけて検出したアプリを抽出している

っぽいんです。

手持ちのアプリで調べたところ、1にも2にも該当しないのに、対象として挙がっているアプリがあるため、リリースされたapkをAnalyzeしてマージ後のマニフェストファイルを調べたところ、

```AndroidManifest.xml
        <receiver android:enabled="true" android:exported="false" android:name="com.google.android.gms.measurement.AppMeasurementReceiver"/>
        <receiver android:enabled="true" android:exported="true" android:name="com.google.android.gms.measurement.AppMeasurementInstallReferrerReceiver" android:permission="android.permission.INSTALL_PACKAGES">
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER"/>
            </intent-filter>
        </receiver>
```

という感じでほとんどのアプリに含まれていることが分かりました。
`com.google.android.gms.measurement`は、GA(Google Analytics)のパッケージですが、実はFA(Firebase Analytics)もGAのパッケージに依存しています。

では、Firebaseの対応がまだなのか？実は最新版では対応済みだったりする？
ということを調べるため、2019/12/11時点で最新のFirebaseバージョンでreleaseビルドして検証してみました。

アプリを取り敢えず新規で作り、Firebaseを導入します。

```app/build.gradle

    implementation 'com.google.firebase:firebase-analytics:17.2.1'
```

※`com.google.firebase:firebase-core`でも一緒です

releaseビルドして(署名ファイルは適当に用意)、Android Studioの[Build]-[Analyze APK..]で見てみると・・・

```AndroidManifest.xml
        <receiver
            android:name="com.google.android.gms.measurement.AppMeasurementInstallReferrerReceiver"
            android:permission="android.permission.INSTALL_PACKAGES"
            android:enabled="true"
            android:exported="true">

            <intent-filter>

                <action
                    android:name="com.android.vending.INSTALL_REFERRER" />
            </intent-filter>
        </receiver>
```

バッチリいます。

これは、Firebaseが対応するのを待つ必要がありそうですね。しばらくは、バージョンアップ情報を注視する必要がありそうです。

（Firebaseの対応が終わってからアナウンスして欲しかった・・・サードパーティー製のSDKの移行は待ったのに、なぜそこを待たない？？　もしかして、Firebaseだけ抜け道を用意するつもりorすでに用意している、とかなのかな。対象アプリ検出ロジックのミスの方かも？）

#追記

- 2020年2月7日  
  https://firebase.google.com/support/release-notes/android?hl=ja#2020-01-14  
firebase-analyticsのバージョンが17.2.2に上がっていますが、INSTALL_REFERRERに関する言及はないですね・・・
カルネージハートとは特に関係のないNuxt.jsで静的生成したファイルをLaravelのBladeに組み込む方法

カルネージハート Advent Calendar 2019 10日目の記事です。

今回はカルネージハートとは全く関係ないNuxt.jsで静的生成したファイルをLaravelのBladeに組み込む方法の話です。

# 前提条件

- Laravel プロジェクト作成済み

## 事前準備
事前準備
npx @vue/cliをインストールする

```console
$ npm i -g npx @vue/cli
```

## LaravelにNuxt.jsのプロジェクトを突っ込む

Laravelのルートディレクトリから

```console
$ npx create-nuxt-app nuxt
```

Nuxtのインストールが完了したら、Nuxtの設定関連ファイル群をLaravelのルートディレクトリに移動させる。

```console
$ cd nuxt
$ mv .babelrc jest.config.js nuxt.config.js package-lock.json package.json ../
```

## Nuxtに必要なモジュールを入れ直す

```console
$ cd -
$ npm i
```

## nuxt.config.jsを編集

```nuxt.config.js
export default {
  srcDir: "nuxt",
  mode: "ssr",
  generate :{
    dir : "public/nuxt" //生成ディレクトリ指定
  },
・
・
・

```

## 静的ファイル生成


```console
$ npm run generate
```

## welcome.blade.php編集

```php
・
・
・
@php 
  echo file_get_contents('nuxt/index.html')
@endphp
・
・
・
```

これで「/」でNuxt.jsで静的生成したファイルをLaravelのBladeに組み込めます！
**index.html以外の静的ファイルのパスが異なるので、nuxt.config.jsのrouterオプションでパスをよしなに変更してください**

## 最後に

事実上の最新作EXAが2010年に発売以降続編の情報が皆無ですが、一部の熱狂的ファンは大会を開催してゲームを続けています。ゲームを盛り上げることで続編も出るかもしれません。カルネジスト、ネジらーの皆様のご協力をお願いします！

カルネージハートファンのプログラミング知識を共有しましょう！
Concrete5 Xamppへのインストール方法

Concrete5をXamppを使ってローカル環境にインストールしたのですが、
[日本版公式サイト](https://concrete5-japan.org/)に載っている情報 [^example] が2014年9月と古かったのでメモ。
どなたかのお役に立てれば幸いです。

ちなみにフォーラムを見ると、コンクリートファイブジャパン株式会社のKatz Uenoさんは[MAMP](https://www.mamp.info/en/)を薦めてます。先人の言うことを素直に聞くことも大切ですね。

> あと、
XAMPP は癖があるので、MAMP の Windows 版をお勧めします。
http://www.mamp.info/en/
こちらであれば、今のところ、問題は少ないようです。

## 構築環境

2019/12/11 現在

- windows7 (64bit)
- Xampp (*v7.3.12*)
    - Xampp Control Panel (*v3.2.4*)
- PHP (*v7.3.12*)
- MariaDB (*v10.4.10*)
- Concrete5 (*v8.5.2*) 

## PHPの設定

`php.ini`を開き変更していきます。

**変更箇所**
[掲載記事](https://concrete5-japan.org/help/5-6/install/install-xampp/)を見ながら変更していきました。

474行目あたり display_errors

```ini:php.ini
display_errors = Off
```

687行目あたり post_max_size
[日本版公式サイト](https://concrete5-japan.org/)の[記事](https://concrete5-japan.org/help/5-6/install/install-xampp/)は20Mですが、デフォルトが40Mだったのでそのままに。

```ini:php.ini
post_max_size = 40M
```

706行目あたり default_charset
ここもデフォルトでコメントアウトされていたのでそのまま。

```ini:php.ini
default_charset = "UTF-8"
```

1669行目あたり mbstring.language

```ini:php.ini
mbstring.language = neutral
```

1677行目あたり mbstring.internal_encoding

```ini:php.ini
mbstring.internal_encoding = UTF-8
```


## MySQLの設定

`my.ini`を開き変更していきます。

**[mysqld]** という文字列をファイル内検索します。
その下の行に追記します。

```ini:my.ini
lower_case_table_names = 2
explicit_defaults_for_timestamp = true
```

147行目あたり innodb_buffer_pool_size

```ini:my.ini
innodb_buffer_pool_size = 32M
```

[日本版公式サイト](https://concrete5-japan.org/)の[記事](https://concrete5-japan.org/help/5-6/install/install-xampp/)にある下記2行はMySQL 5.7で削除されたようで
記述するとエラーになるので注意！
`innodb_additional_mem_pool_size = 2M`
`innodb_use_sys_malloc = 1`


---

上記の設定を終えてやっとConcrete5をインストールできました。



参考サイト
- [concrete5をローカル（XAMPP）に入れてみた](https://hanakomachi.wordpress.com/2014/11/28/concrete5-xampp/)
- [えっ、たったこれだけ？concrete5をXAMPPの仮想環境で動かしてみる](https://www.aiship.jp/knowhow/archives/24964)


[^example]: [XAMPPへのインストール :: concrete5 Japan 日本語公式サイト](https://concrete5-japan.org/help/5-6/install/install-xampp/)
ElasticTranscoderでサムネイルサイズを調整する方法

Lambda関数からElasticTranscoderを呼び出し、動画変換処理を行う際、サムネイルも自動で出力することができます。しかし、デフォルトで作成されるサムネイルはサイズが小さく、viewで表示するととても荒くなってしまうので、サイズを調整したくなったのでやり方をまとめてみました。

サムネイルのサイズを調整する方法は以下の通りです。

1. AWSから「`Elastic Transcoder`」を選択
1. 左側サイドバーの「`Presets`」を選択
1. 任意のプリセットをチェックし、画面上部の「Copy」をクリック
1. 画面下部の「Thumbnail」の項目から「Height」「Width」を入力
1. Lambda関数で呼び出す際には、ここで作成したPresetIDを指定する
【Rails】Facebookでログインできるようにする

# バージョン
`Rails 5.1.6`
`ruby 2.4.0`

#前提
devise導入済み
herokuにデプロイする

#1.Gemfileの編集
```Gemfile
gem 'omniauth'
gem 'omniauth-facebook'
```
を追加して

```
$ bundle 
```

#2. Facebook Developerの登録
https://developers.facebook.com/
にてアクセス

![Screen Shot 0001-12-11 at 15.34.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212678/f12270a8-3ba8-9416-43c1-f883ee9fe72f.png)


![Screen Shot 0001-12-11 at 15.35.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212678/2f1634c4-4cbb-2c54-62b0-d577df520ba9.png)

facebookログインを追加

すると、右側のメニューにfacebookログインという項目が追加される

#3.色々な設定
![Screen Shot 0001-12-11 at 15.40.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212678/a949a663-ff35-ce20-3be8-77b5c6c3b897.png)

プライバシポリシーのURLを埋める
私の場合、プライバシーポリシのページを作ってなかったので適当に拝借しました

## 本番環境では有効なOAuthリダイレクトURIの設定が必要
facebookログイン > 設定 > 有効なOauthリダイレクトURLに
`...(サイトURL)/users/auth/facebook/callback`を設定

#4.Railsでの設定
omniauth用のカラムをuserモデルに追加

```terminal
$ rails g migration add_columns_to_users provider uid name image
$ rails db:migrate
```

```ruby:config/initializers/devise.rb
Devise.setup do |c|
  c.omniauth :facebook, 'App ID', 'App Secret'
end
```
※ このままgitのリモートリポジトリにあげないこと

### userモデルにメソッドを追加

```ruby:models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable # :omniauthable を追加

  def self.form_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |u|
      u.provider = auth.provider
      u.uid      = auth.uid
      u.name     = auth.name
      u.email    = auth.info.email
      u.password = Devise.friendly_token[0, 20]
      u.image    = auth.info.image.gsub("picture", "picture?type=large") if u.provider == "facebook"
   end
  end
end
```

### コールバックの設定
```ruby:config/routes.rb
Rails.application.routes.draw do
  root to: "home#index"
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
end
```

### コントローラの設定
```ruby:controllers/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"]
    
    if @user.persisted?
      sign_in_and_redirect @user, event: authentication
      set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"].except("extra")
      redirect_to new_user_restration_url
    end
  end

  def failure
    redirect_to root_path
  end
end
要素配置時のポイント【ポートフォリオ作成編】

**こんにちは。ばーんです。**

サイト作成中に
###「要素を思い通りの位置に配置できない！」
となった際のポイントを纏めています。
（実際に自分が克服した方法）


今回作成したい完成図がこちら↓
<img width="416" alt="スクリーンショット 2019-12-10 12.06.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534071/b2310e1a-8b6b-208f-ed70-294ce877e1b5.png">

実際に作成するとわかるのですが、要素が細かくあるため、テキトーに配置していくと、後で大惨事になります…

今回苦戦したのが↓の③「Profile」[Work]ボタンです。
<img width="416" alt="スクリーンショット 2019-12-10 12.06.01 2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534071/2d38a052-a6ea-8bb8-f608-516311472804.png">

divでボタンを作って…
で配置すると↓こうなりました。
<img width="416" alt="スクリーンショット 2019-12-10 12.06.01 3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534071/f4e230a1-6d32-da40-caf9-cb41f6a8c1e2.png">

**そうだ、そうだ！inline-blockにしないと**
でdisplay指定すると…
<img width="416" alt="スクリーンショット 2019-12-10 12.06.01 3 2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534071/4cca5ee6-f0c4-69da-0fba-354b35751ae3.png">

####なんでfloatもしてないのに、回り込むの(ToT)

ここで四苦八苦します（変なスタイルあたってないか検証見たりしてもダメ）。
position:relativeで無理やり動かすと、レスポンシブ対応ができない…

相当時間を費やした後、冷静になります。

#今の要素を書き出してみよう。

実際はこんな感じです↓
![IMG_20191211_153111.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534071/8583b3bf-1027-cd19-f12a-6baaf1d09390.jpeg)

ここで正解にたどり着きました。
親要素がないので（一番大枠のdivが親要素になってるので）、
横並びになってました！

<img width="416" alt="スクリーンショット 2019-12-10 12.06.01 2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534071/5176fd24-b458-79aa-4e4b-ee9d48b44fa2.png">

なので、↑の写真で言うと❷と❸を括った親要素が必要だった！
ということですね。

というわけで、配置に困った時のポイントは、
#「今の要素を書き出してみる」
でした。

最後まで見て頂いてありがとうございましたm_ _m
Python(Flask)のプロジェクトで途中からLinterを導入しようとした話

## 話題
- 参画しているプロジェクトのバックエンド(Flask)のコードがLinterやformatterが導入されておらず苦労した(なお継続中)話

## 希望
- Githookでlint&formatしたくね？？？？？？


## 問題
- プロジェクト初期に書かれたコードがpep8ガン無視でlint導入したらエラー出まくる
- 一気にautofixかけたいけど、差分が出過ぎてレビューができない。
- 全量リファクタもしたいが工数もないし、テストコードも十分じゃなさそう

## 妥協
- 新規作成するコードはLint&formatかける。
- 既存コードは一旦そのまま
- 既存コードのテストコードを見直し、追加実装していつでもリファクタできるようにしておく
- hookでLintはかける。formatはにんげんが判断してかける(苦肉の策)。
- 既存は`git commit --no-verify`で無理矢理コミットする

### 開発方法
#### 新規の場合
1. コーディングする
2. コミット時にLintが走る
3. formaterをかける `black hogehoge.py`
4. 手で直さなきゃならないとこはエラーがなくなるまで修正してコミット(ファイル指定でlint`flake8 hogehoge.py`)
5. pushしてプルリクレビューへ

#### 既存コードに手に入れる場合
1. コーディングする
2. コミット時にLintが走る
3. エラーがあれば、`black hogehoge.py --diff`で追記部分のエラーを確認して手で直す。(ファイル指定でlint`flake8 hogehoge.py`)
4. コミットするときは`git commit --no-verify`でhookを飛ばす
5. pushしてプルリクレビューへ

## Linterの設定
linterは[flake8](https://gitlab.com/pycqa/flake8)を利用する。
1. `pip install flake8`
2.  設定ファイルを作成(プロジェクトルートに`.flake8`を作る)

```.flake8
[flake8]
ignore = E203, E266, E501, W503, F403, F401
max-line-length = 79
max-complexity = 18
select = B,C,E,F,W,T4,B9
```

#### ※flake8の設定は適宜変えること
- 正直現代でmax-line-length<80は少なすぎ
- igonoreはblackとの関係でE203,W503,W504は必須。それ以外は適宜
- [ここ見て](https://lintlyci.github.io/Flake8Rules/)


## formatterの設定
formatterは[black](https://github.com/psf/black)を使う
1. `pip install black`
2. 設定ファイルを作成(プロジェクトルートに`pyproject.toml`を作る)

```pyproject.toml
[tool.black]
line-length = 79
include = '\.pyi?$'
exclude = '''
/(
    \.git
)
'''
```
#### flake8と合わせること
- たまにformaterかけたのにエラーになるときあってびっくりする

## githookの設定
hookの設定には[pre-commit](https://github.com/pre-commit/pre-commit/)使います。
1. `pip install pre-commit`
2. 設定ファイルの作成(プロジェクトルートに`.pre-commit-config.yaml`を設置)

```
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
hooks:
- id: flake8
```

## まとめ
- ツールの導入期間なこともあっていびつで手作業が含まれてしまってる。ちょっとずつ変えていく
- linterやformaterは最初に入れる。ルールも最低限のもの(pep8)入れるべき
- 書きづらいなと思った段階でルールを変えていく
- テストコードがちゃんとしてれば既存いじっても基本は問題ない
facebook-ruby-business-sdkで広告結果データを取得しchartkickでグラフ化

## 実装したいこと
- facebookページでかけた広告結果データを取得して画面描画したい
- 広告結果データ取得には[facebook-ruby-business-sdk](https://github.com/facebook/facebook-ruby-business-sdk)を使う
- グラフ描画には[chartkick](https://chartkick.com/)を使用する

## トークン取得

[developer for facebook](https://developers.facebook.com/)にアクセスしてアクセストークンを取得します、下記キャプチャから取得できます

![WOW_U_―_マーケティングAPI_-_Facebook_for_Developers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348703/e0aa6f80-4eac-182c-0404-a5e33f97ec69.png)

画面左側メニューの「設定 > ベーシック」から「**app secret**」も取得できるので、これも控えておきます。

ここで取得したトークンとシークレットをcredentialsに入れておきます。

## Railsアプリから呼び出す

トークンを設定できたら呼び出す準備は完了しているので、必要な記述を追加していきます。

#### taskテーブル
| カラム名 | 型 |
----|----
| name | string |
| ad_id | string |

#### dataテーブル
| カラム名 | 型 |
----|----
| impressions | integer |
| country_name | string |
| task_id | bigint |

`task has_many datas`

タスクを登録した時に、広告結果を取得してみます。

```ruby:app/models/task.rb

require 'facebookbusiness'

class Video < ApplicationRecord
  # facebook marketing API
  FacebookAds.configure do |config|
    config.access_token = Rails.application.credentials.dig(:facebook_ads, :access_token)
    config.app_secret = Rails.application.credentials.dig(:facebook_ads, :app_secret)
  end

  # callback
  after_save :fetch_facebook_insights

  def fetch_facebook_insights
    ad = FacebookAds::Ad.get(ad_id)
    insightss = ad.insights(
      fields: 'impressions',
      breakdowns: 'country',
      date_preset: 'this_quarter'
    )
    insightss.all.each do |insight|
      data.create(
        country_name: insight.country,
        impressions: insight.impressions.to_i
      )
    end
  end
end
```

地味に気を付けたい点としては、

- impressionsが`String`で返ってくるので型変換が必要
- countryは `AU`などの略称で返ってくるので、UIで日本語表示したい場合は対応が必要


２点目については、[facebookの国コード一覧](https://developers.facebook.com/docs/accountkit/countrycodes/)などが役に立つかと思います。


## chartkickでグラフ化

READMEに沿って進めれば簡単にグラフ化できます。

https://github.com/ankane/chartkick

```rhtml:show.html.erb
<%= bar_chart @task.datas.group(:country_name).sum(:impressions) %>
```
Rubyの変数の定義(インスタンス変数)


##Rubyの変数の定義について、今回はインスタンス変数

前回は[ローカル変数](https://qiita.com/nyan_tech_24/items/bf52e294e86910d23570)について書きました

続いてインスタンス変数です。

## 命名規則
変数の先頭は@
変数の構成は英数字と_

```ruby
@student = "Taro"
@_student_2 = "Jiro"
@STUDENT_3 = "Sabu"
@4_STUDENT_4 = 'Fourth'   #@の隣に数字は定義できない
SyntaxError:`@4' is not allowed as a class variable name 
#ちなみに初期値を設定しないで呼び出すと「nil」になる
@student_5 
puts @student_5

=> nil
```

## スコープ
そのインスタンス内で参照できる

```ruby
@student = "Taro"  #インスタンス変数を定義 ことのき"Taro"というStringクラスのインスタンスが生成

puts @student 
Taro
=> nil

3.times do |n|
  puts @student
end
Taro
Taro
Taro
=> 3 

def students
  @student
end
students           #Stringクラスを継承しているインスタンス内なので参照が可能
Taro
=> nil

class Students
puts @student  
end
                      #クラスの外部の@studentをクラス内部で読み込むことはできない
=> nil
```
ではなぜStudentsクラスから@studentが呼び出せないか。
理由はインスタンス変数はインスタンス内で参照ができるからです。
どういうことか？そもそもインスタンスとはなにか？？

インスタンスとは
クラスは設計図でクラスで作られたものがインスタンスです。
たとえば

```ruby
@student = "Taro"  
@student.class
=> String
```

のように@studentはStringクラスのインスタンスです。
たとえばこうすると

```ruby
@student = 123  
@student.class
=> Fixnum
```

となり@studentはFixnumクラスのインスタンスとなるのです。

つまりStudentsクラスで作ったインスタンスであれば、インスタンスごとにStudentsクラス内で呼び出すことができます。

```ruby
class Students
  def name=(name)
    @student = name
  end
  def greet
    puts "Hi,#{@student}！！"
  end
end
a = Students.new 
a.name = "Hanako"
a.greet
"Hi,Hanako!!"

b = Students.new 
b.name = "Yoshiko"
b.greet
"Hi,Yoshiko!!"
```

インスタンスを作成するごとに、インスタンス変数に値を代入して呼び出すことができる。

ただしこれだといちいちインスタンスを呼び出して値を代入しないといけないので、インスタンスを作成するタイミングで値を引数に入れて代入する[initializeメソッド](https://qiita.com/nyan_tech_24/items/ea852c7f93a07d4d3ec0)を使うのが一般的かなと思います。

```ruby
class MedicalStudents
  attr_accessor :name             
  def initialize(name)  
    @student = name       
  end
  def greet          
    "Hi,#{@student}!!"   
  end
end

a = MedicalStudents.new("Hanako")
a.greet
"Hi,Hanako!!"
a.name = "Yoshiko"
a.geet
"Hi,Yoshiko!!"
```

以上がインスタンス変数でした。

またインタンスの生成などはオブジェクトとはの段階から理解したほうが良いということが分かりました。

ここでは詳しく説明してないので次回以降に書けたらいいなと思います！！
# LibVLCSharpでVLC(RTSP)と戦った時のメモ

# LibVLCSharpでVLC(RTSP)と戦った時のメモ

使ったのはここら辺

- LibVLCSharp.Form 3.3.1
  - VideoLan.LibVLC.iOS 3.1.5.1
  - VideoLan.LibVLC.Android 3.2.0
- Visual Studio 2017 15.9.17
  - Xamarin.Android SDK   9.1.7.0 (HEAD/ba9da7a76)
  - Xamarin.iOS and Xamarin.Mac SDK   12.4.0.64 (9c8d8e0)

## libvlc

- libvlc はスレッドセーフ https://forum.videolan.org/viewtopic.php?t=84269
  <br>media_list は media_list_lock とか必要
  <br>libvlc インスタンスは別スレッドで共有しちゃダメ
- RTSP の TCP 接続タイムアウトはオプション ipv4-timeout が利用される
- データが来ない時(RTP?)のタイムアウトはここら辺でハードコード(ucast約10秒 mcastは41秒) されている
  <br>https://github.com/videolan/vlc/blob/master/modules/access/live555.cpp#L1477
- RTSP サーバーのタイムアウトする値が0の場合60秒へ置き換える処理がハードコードされている (仕様っぽい)
  <br>https://github.com/videolan/vlc/blob/master/modules/access/live555.cpp#L1273
- なんで誰も libvlc_media_player_stop でハングするの直せねーんだよ https://forum.videolan.org/viewtopic.php?t=147724
  <br>ほんとにね

## LibVLCSharp

- スリープ時に再生停止が必要
  <br>MediaPlayer 作り直しが良さげ
- Media.Parse() iOS でよく固まる
  <br>MediaPlayer に Media 渡して任す方がよい (事前にメディア情報取れんがな...)
- MediaPlayer, Media (LibVLC も?) の IDisposable.Dispose() 呼ばずに GC 回収の方が安全
  <br>リソース速攻破棄している副作用で例外?
- Android でハードウェアアクセラレーションを有効化すると例外が起きる端末がある
  <br>iOS は大丈夫
- MediaPlayer.Stop() で固まる
  <br>Xamarin.Android のバグ? https://code.videolan.org/videolan/LibVLCSharp/issues/123
  <br>RTSPは仕様上長い
- MediaPlayer.EndReached iOSで複数再生時に不適切なイベントが発生するAndroidでは起きない
  <br>別のイベントにやってきているかファイルの扱いが微妙に違うかも
- バッファが小さいと iOS で例外
  <br>2000ms 以上必要?
- MediaPlayer.IsMute を制御すると iOS で例外
  <br>iOS の音声周り怪しい?

Media.Parse() MediaPlayer.Dispose() を呼んでいた時の出会いが混じっているので呼ばなければ幾分大丈夫なのかもしれない
私が欲しいのはruby2.3.1。ruby2.3.1がなぜかinstallできない件。middlemanをローカルで動かそうと思ったら、突然動かなくなった件について

今まで普通に動いていたmiddlemanのローカルサーバー。

突然次の日middlemanのローカルサーバーを動かそうと思ったら、動かなくなりました・・・なんで？

ボスに教えてもらいながら、解決方法を片っ端から実践して見たことをここに書こうと思います。

**slackだと消えてしまうのと、
私のような人がいた時のヘルプになれるように。**

# まずやったこと
**ruby 2.3.1**を使っていて難なく動いていたが、突然動かなくなってしまったので、仕方なく**ruby2.3.1**のアンインストールを実行する。

```shell-session
rbenv uninstall 2.3.1
```

## 次にやったこと
**ruby2.3.1**のインストールを実行するがなぜか入らない・・・。とっても困りました。

エラーが出現↓

```shell-session
ruby-build: using readline from homebrew
BUILD FAILED (OS X 10.13.6 using ruby-build 20190828)
Inspect or clean up the working tree at /var/folders/ry/yfy244t51blb55lmrdq02wcc0000gn/T/ruby-build.20191206153836.44874
Results logged to /var/folders/ry/yfy244t51blb55lmrdq02wcc0000gn/T/ruby-build.20191206153836.44874.log
Last 10 log lines:
ERROR: Ruby install aborted due to missing extensions
Configure options used:
  --prefix=/Users/Himekichi/.rbenv/versions/2.3.1
  --with-reaine-dir=/usr/local/opt/readline
  --with-openssl-dir=/usr/local/opt/openssl@1.1
  --with-readline-dir=/usr/local/opt/readline
  CC=clang
  CFLAGS= -O3 -Wno-error=shorten-64-to-32
  LDFLAGS=-L/Users/Himekichi/.rbenv/versions/2.3.1/lib
  CPPFLAGS=-I/Users/Himekichi/.rbenv/versions/2.3.1/include
```

##ほんでまた次にやったこと
似たような事例がネットにあったので、試して見ました。
https://qiita.com/Axl178TakLoose/items/861e953e998f232a1bd8
これも効果なく撃沈。

##次にやったこと
`brew update`
`brew install openssl`
これでもだめ・・・。

##次へ進む
ruby versionをなるべく新しいものへ変更。

middlemanで動く一番新しいバージョンは**ruby2.4.1**

##最新ruby versionは入るのか？古いruby versionは入るのか片っ端から実験スタート
**結果**

**ruby2.3.1 入らない**
`ruby2.3.2`　入らない
`ruby2.4.1`　入らない
`ruby2.4.3`　入る
`ruby2.4.4`　入る
`ruby2.5.1`　入る
`ruby2.5.2`　入らない
`ruby2.5.6`　入る
`ruby2.6.1`　入る
`ruby2.6.4`　入る

(少し数が飛んでいるのは、私のパソコンにすでにそのバージョンが入っているからです。)

そこで上記に書いてあることを一通りした後にruby2.3.1が入るか再度試してみることにした。
かなりダメ元、プラスやけくそでw。
 `$ rbenv install 2.3.1`
**結果入りました！！！いええええええい。でもなんで**

なぜruby2.3.1が急に入ったのかは定かではありません。（今の所）

##次へ進む
とりあえず`ruby2.6.4`が入ったならば、
gemのバージョンをあげて動作すれば問題なしということで実行。

あとはxcodeが入っていないとmiddleman動かないとか書いてあった記事がどこかにあったような気がする。
xcodeはすでにもうインストール済みなので、これは問題ではない。

じゃあ結局原因はなんなんだということで今日も原因究明は続きます・・・・・・・・
Windowsでよく使うレジストリ~2~

## はじめに
Windowsでよく使うレジストリ~1~の続きになります。

## 設定の仕方

GPOで作成するのと直接記入する時は設定方法が変わります。
それぞれの場所は以下の通りになります。

<b>1.GPOの場合</b>
・コンピュータで設定を統一したい場合は
　　<b>コンピュータの構成\基本設定\Windows の設定\レジストリ</b>
・ユーザーで設定を統一したい場合は
　　<b>ユーザの構成\基本設定\Windows の設定\レジストリ</b>

<b>2.直接レジストリに書き込む場合</b>

*<font color="Red">※直接書き込むときはバックアップ(エクスポート)を忘れずに!</font>*

スタートボタン(Windowsボタン)+Rで検索ボックスを起動し、ボックス内にregeditと入力して
レジストリエディタを起動します。

## 3. 資格情報の保存
*WebページのBASIC認証時におけるIDとパスワードを記憶させたい場合に使います*

### ・パスワードキャッシュを有効
*レジストリの場所*

```
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
```
*設定値*
  値の名前 : DisablePasswordCaching 
  値の種類 : REG_DWORD 
  値のデータ : 0
　有効 : 0
　無効 : 1

## 4. デスクトップアイコンとショートカットの表示

*<font color="Red">※デスクトップ アイコンの指定はCLSIDを使用します。</font>*

*デスクトップ アイコンのCLSID*
コンピューター : {20D04FE0-3AEA-1069-A2D8-08002B30309D}
ユーザーのファイル : {59031a47-3f72-44a7-89c5-5595fe6b30ee}
ネットワーク : {F02C1A0D-BE21-4350-88B0-7367FC96EF3C}
コントロール パネル : {5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}
ごみ箱 : {645FF040-5081-101B-9F08-00AA002F954E}

### ・ コントロールパネルアイコンを表示させたい場合
*レジストリの場所*

```
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel
```
*設定値*
  値の名前 : {5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0} 
  値の種類 : REG_DWORD 
  値のデータ : 0
　有効 : 0
　無効 : 1

## 5. フォルダーの設定
### ・ エクスプローラをPCで開く

*レジストリの場所*

```
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
```
*設定値*
  値の名前 : {5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0} 
  値の種類 : LaunchTo 
  値のデータ : 1
　有効 : 1
　無効 : 0

## 6. ホームページの設定(IEのみ適用)
### ・ スタートページの設定
*IEを起動させたときに最初に表示されるトップページの設定したい場合に使います*
*レジストリの場所*

```
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main
```
*設定値*
  値の名前 : Start Page 
  値の種類 : REG_SZ 
  値のデータ : ホームページのURLを指定する

### ・ 複数のホームページのタブ
*IEを起動させたときに複数のホームページタブを設定したい場合に使います*
*レジストリの場所*

```
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main
```
*設定値*
  値の名前 : Secondary Start Pages 
  値の種類 : REG_MULTI_SZ 
  値のデータ : ホームページのURLを指定する(複数のホーム ページのタブを指定する場合は「\0」で区切る)
駆け出しエンジニアの初投稿

テックエキスパートに通い１ヶ月ほど、htmlやcss、ruby、railsを学んだがほとんど理解できていない。
今から応用のカリキュラムを始めるが、チャットスペースというのをやるらしい。
果たして大丈夫なのか、そもそも自分が一人前のエンジニアになれるのかと考えてしまう。
学んだことを、投稿して行くので、間違いがあったり助言してもらえると嬉しいです。
Dockerコマンドを使いこなそう

#はじめに
Dockerコマンドの操作方法を復習していきます。
Docker環境がまだ無い方は以下の記事を参照してみてください。

参考：[今話題のDocker + Rails + Circle CI + Terraform構成を試したいんじゃ！](https://qiita.com/gggnt/items/ceb1d2ec5f8167aaa74c)


#コマンド
##確認系
###docker ps
コンテナの状態確認
-a をつけることで停止中のコンテナも表示できる

```shell:docker&nbsp;ps&nbsp;-a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                   PORTS               NAMES
e8f5056d7bf4        hello-world         "/hello"            3 hours ago         Exited (0) 3 hours ago                       ecstatic_snyder
```


###docker images
ローカルにあるイメージファイルの一覧

```shell:docker&nbsp;images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              fce289e99eb9        11 months ago       1.84kB
```



###docker info
Dockerの状態を確認
ダッシュボード的存在

```
[root@localhost docker]# docker info
Client:
 Debug Mode: false

Server:
 Containers: 1
  Running: 0
  Paused: 0
  Stopped: 1
 Images: 2
 Server Version: 19.03.5
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 ＜略＞
```


##操作系

####docker start/stop
コンテナの起動/停止

```
###コンテナの起動
# docker start <コンテナ名>

###コンテナの停止
# docker stop <コンテナ名>
```


###docker pull
Dockerイメージのダウンロード

```shell:（例）CentOS7のイメージダウンロード
# docker pull centos:7
```

###docker run
コンテナ起動

```
# docker run -it -d -p <ホスト側ポート>:<コンテナ側ポート> -v <ホスト側ディレクトリ>:<コンテナ側ディレクトリ> --name <コンテナ名> <Dockerイメージ名>
```
**run オプション**

|オプション|説明|例|
|:------|:------|:------|
|--name|コンテナ名を指定|docker run --name "test" centos|
|-d|バッググラウンド実行|docker run -d centos|
|-it|コンソールに結果を出力|docker run -it --name "test" centos /bin/cal|
|-p host:cont|ポートフォワーディング|docker run -d -p 8080:80 httpd|
|--add-host|ホスト名とIPを指定|docker run -it --add-host=test.com:192.168.1.1 centos|
|--dns|DNSサーバを指定|docker run --dns=192.168.1.1 httpd|
|--mac-address|MACアドレスを指定|docker run -it --mac-address="92:d0..." centos|
|--cpu-shares|CPU配分 (全体で1024)|docker run --cpu-shares=512 centos|
|--memory|メモリの上限|docker run --memory=512m centos|
|-v|ディレクトリの共有|docker run -v /c/Users/src:/var/www/html httpd|
|-e|環境変数を設定|docker run -it -e foo=bar centos /bin/bash|
|--env-file|環境変数リストから設定|docker run -it --env-file=env_list centos /bin/bash|
|-w|作業ディレクトリを指定|docker run -it -w=/tmp/work centos /bin/bash|


###docker cp
コンテナ-ホスト間のファイルコピー

```
###コンテナ→ホストへのファイルコピー
# docker cp <コンテナ名>:<コンテナ内のコピー元ファイル> <ホスト側のコピー先ディレクトリ>

###ホスト→コンテナへのファイルコピー
#　docker cp <ホスト側のファイル> <コンテナ名>:<コンテナ内のコピー先ディレクトリ>
```

###docker exec
コンテナへのログイン


```shell:（例）『tomcat』コンテナへログイン
[root@localhost docker]# docker exec -it tomcat bash
[root@e01ba3d18e31 /]#
```
###docker commit
コンテナからdockerイメージの作成

```
# docker commit <コンテナ名> <作成するDockerイメージ名>
```

###docker rm(i)
コンテナ（dockerイメージ）の削除

```
###コンテナの削除
# docker rm (-f) <コンテナ名>

###dockerイメージの削除
# docker rmi (-f) <dockeriイメージファイル名>
```

#今日はここまで
新しく覚えたコマンドは追記していきます。
ユーザー属性によってdeviseの新規登録フォームを変える方法

## 実装したいこと
- ユーザー属性によって異なるフォームパーツを出力する
  - 会社ユーザーであれば、会社名・email・password
  - 通常ユーザーであれば、email・password 
- 認証周りは[devise](https://github.com/plataformatec/devise)で一括管理したいけれど、むやみにcontrollerやviewを増やしたくない


## 結論: パラメータで条件分岐

deviseのcontrollerは `users` 下のものを使用する

```ruby:routes.rb
devise_for :users, controllers: {
  sessions: 'users/sessions',
  registrations: 'users/registrations',
  passwords: 'users/passwords',
  confirmations: 'users/confirmations'
}
```


```ruby:app/controller/users/registrations_controller.rb

# GET /resource/sign_up
def new
  super do |resource|
    if params[:as] == 'company'
      build_resource({})
      self.resource.company = Company.new
    end
  end
end
```

```rhtml:app/views/users/registrations/new.html.erb
<% if params[:as] == 'company' %>
  <h2 class="has-text-weight-bold">会社アカウント作成</h2>
  <%= f.fields_for :company do |company_form| %>
    <div class="field">
      <%= company_form.label :name, class: 'label has-margin-top is-inline-block' %>
      <span class="has-text-danger">*</span>
      <%= company_form.text_field :name, autofocus: true, class: 'input'  %>
    </div>
  <% end %>
<% end %>
```

こんな感じで書いておけば、パラメータで `company`が渡ってきた時だけ、フォームパーツを出力することができます。


```ruby:app/controller/application_controller.rb
before_action :configure_permitted_parameters, if: :devise_controller?

private
def configure_permitted_parameters
  devise_parameter_sanitizer.permit(:sign_up, keys: [company_attributes: [:name]])
end
```

サインアップの時にパラメータを送信できるよう許可しておく必要があります。

参考: https://github.com/plataformatec/devise#strong-parameters
弊社CTOから学ぶCTOに関する考察

# 弊社diffeasyにはCTOが存在する

CTOという生き物は得てして多くは語らず
持ち得る技術でその地位を確固たるものとしている事が多いが
弊社CTO（以降N氏と呼ぶ）は一般的なCTOの持つイメージとも違い
突出したスキルだけでdiffeasyの個性的なエンジニア勢を
魅了しているわけではない。
もちろん技術も知見も持ち合わせてはいるが
それ以外のN氏の持つ魅力から弊社におけるCTOとは
どういうポジションなのか考えてみることとする

## N氏は38歳。

一昔前ならエンジニアとしては定年と言われる年である。
彼は十分な経験に裏付けられた威厳を感じさせるところもあるが
プライベートは素敵な家族のいるベンチャー企業のCTOという
世間から見ればキラキラ要素満載なおじさんである。

しかし彼の自分像の乖離のようなものはSNSでの言動から垣間見ることができ
**CTOとしての尊厳**と**イジられたいおじさん**としての葛藤を伺える。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">「モーターショーにも多少興味ある」ってダジャレを思いついた。<a href="https://twitter.com/hashtag/%E3%83%80%E3%82%B8%E3%83%A3%E3%83%AC%E3%81%AE%E3%82%80%E3%81%9A%E3%81%8B%E3%81%97%E3%81%84%E3%82%92%E7%B0%A1%E5%8D%98%E3%81%AB?src=hash&amp;ref_src=twsrc%5Etfw">#ダジャレのむずかしいを簡単に</a></p>&mdash; にっしー - diffeasy CTO (@_takeshi_24) <a href="https://twitter.com/_takeshi_24/status/1181783771332431872?ref_src=twsrc%5Etfw">October 9, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

`#ダジャレのむずかしいを簡単に` というハッシュタグの
比較的新しい投稿を紹介したが2018年以前より
彼のみが投稿していることを確認できる。

他にも急に真面目なことを呟いたかと思えば
誰も突っ込まないしょうもないことを言ったりもする

その発言は沢山の賛同が集まることも炎上もしない
CTOとはある程度孤独なものなのかもしれない

ただ彼は確実に何らかのレスポンスを期待している
もし見かけたときは💗の一つでもつけてあげてほしい
（そして彼は他人のダジャレには非常に厳しい）

## 独特なコミュニケーション

福岡市はその狭い中にIT企業が密集しており
活発なエンジニアのコミュニティも形成されやすい。

福岡での活動も長いN氏は顔も広く
エンジニアにはdiffeasyといえばN氏というぐらいの存在感を示している。
もちろんビジネスとしての交流も欠かさず有り難いことに
沢山のお仕事のお話を頂きN氏はPMとしてお客様と接することもある。
このコミュニケーション能力や折衝力は非エンジニアでも欲しいスキルである。

一方で彼はSNS上で**焼肉おじさん**という謎の肩書を持っている。
社外の方と積極的にランチでのコミニュケーションを取るために
頻繁に焼肉を食べることでその地位を確立していたが
最近ではその活動は著しく縮小している。
38歳のおじさんに頻繁な焼肉は負担が大きい。
また彼はそこまで焼肉が好きというわけではない [要出典]

## 社内での扱われ方
もちろん社内では最高技術責任者として会社の役員として
尊敬される存在となっている。と思っていた。
よくよく考えれば当たり前のことだが人生において尊敬する人など
生きてるうちに一人でも見つかればいいぐらいのもので
そんなに身近にいてはいけないし身近にいるのだから追いつける存在である。
N氏は自分も人間でありエンジニアであり成長過程でその姿を見せることで
こういう歩み方もあるのだと背中で語っているような気がする。
気がするだけかもしれない。ちなみに私からはとても雑に扱われている。

家族からも何考えてるかわからないと言われるN氏だが
その姿はごく普通の38歳エンジニア男性そのものである。
もし本当に尊敬している人がいたら
声に出して尊敬していますと言ってあげて欲しい。
弊社には私が作成した彼の写真集があるのでお越しの際には
N氏のプライベートな素顔をごらんください。

## 意思表明
CTOとしての意思は以下の記事から読み取る事ができる。

・[ベンチャー企業におけるエンジニアと組織の成長、そしてCTOの役割を考える
](https://note.com/_takeshi_24/n/ne934b1462b0f)
・[拝啓diffeasyエンジニアの皆様へ
](https://note.com/_takeshi_24/n/n2d9b45ad55ab?creator_urlname=_takeshi_24)

これはあくまで本人の考えるCTO像であって果たしてそれが
組織にとってどのような影響を与えたのかはdiffeasyが
今よりも遥かに大きくなったときにわかるものだと思う。
大切なのはこういった意思表明が出来ることである。
組織で働くエンジニアにとってCTOは「頼れる存在」であり
「エンジニア組織としての未来」を司る象徴である。
一般的なエンジニア組織ではCTOの一言によって技術は選定され
ときにはそれが他のエンジニアのモチベーションを
大きく左右することにもなりかねない。
彼自身がモノを作ることの楽しさを忘れていないことが
クリエイティブなエンジニアが多い弊社にとっては
何よりも働きやすい環境を用意してくれていると思う。

## 総評
弊社にとってCTOは
・誰よりもエンジニアらしいものづくりが好きな男
・決して技術も思想も強制もしないし排除もしない
・決して威張らず出し惜しみもしない会いに行けるアイドルのようなもの

エンジニアが半数以上を占める組織にとって
CTOは肩書以上にその組織の色を表しているし
エンジニア目線で見るとdiffeasyにとってのN氏はdiffeasyそのものである。

PS、西さんいつも色々ありがとうございます。来年もよろしくです。
「firenvim」のセットアップ方法&使い方

## 「firenvim」とは？

TBD

## セットアップ

### プラグインのインストール

Neovimにプラグインをインストールします。

```toml:dein.toml
[[plugins]]
repo = 'glacambre/firenvim'
hook_post_update = 'call firenvim#install(0)'
```

### 拡張機能のインストール

Chrome
https://chrome.google.com/webstore/detail/firenvim/egpjdkipkomnmjhjmdamaniclmdlobbo

Firefox
https://addons.mozilla.org/en-US/firefox/addon/firenvim/

## 参考リンク

- [glacambre/firenvim: Embed Neovim in your browser.](https://github.com/glacambre/firenvim)
- [ブラウザのテキストエリアでNeovimを使う ｜ Developers.IO](https://dev.classmethod.jp/etc/shuntaka-browsernvim-20191103/)
xib で定義されてる cell の使いやすくようにする

## 問題点

ベタ書きでエラーが発生する可能性は十分あるんで悩ましい。

``` swift
let nib = UINib(nibName: "MyCell", bundle: nil)
```

か

```swift
tableView.register(UINib(nibName: "MyCell", bundle: nil), forCellReuseIdentifier: "MyCellIdentifier")
```


## やりたいこと

- Embedded Framework 対応
    - bundle に入れるべき値は cell class によって変わる
- nibNameの入れ方をスマートに


## 解決方法

### String(describing:)

``` swift
let nibName = String(describing: MyCell.self)
```

- 参照 - https://qiita.com/vc7/items/91070050646ecbf21ae3

### 動的に Bundle を取得

``` swift
let bundle = Bundle(for: MyCell.self)
```

Bundle が動的に取得できれば Cell が他の target/framework に定義されても困らない。

### 合併してみる

合併したらこんな感じになります

``` swift
let nibName = String(describing: MyCell.self)
let bundle = Bundle(for: MyCell.self)

let nib = UINib(nibName: nibName, bundle: bundle)
```

## よしなにヘルパーを設ける

``` swift
extension UITableViewCell {
    public static var nib: UINib {
        return UINib(nibName: nibName, bundle: Bundle(for: self))
    }

    static var nibName: String {
        return String(describing: MyCell.self)
    }
}
```

### 使い方

``` swift
tableView.register(MyCell.nib, forCellReuseIdentifier: "MyCellIdentifier")
```

この書き方にするなら、ヒューマンエラ可能性も低くになると思います。
次は cell reuse identifier の方を書こうと思います。