OmniAICreator/Qiita-1.07M huggingface dataset:
rbenv が入った docker image を作りたい人生だった

# はじめに

rbenv の入った docker image を作りたかった。
OS は ubuntu を使うことにした。


# Dockerfile

```yaml:Dockerfile
FROM ubuntu:xenial

# Require to install ruby
RUN apt-get update && \
    apt-get install -y \
    git \
    build-essential \
    libssl-dev \
    libreadline-dev \
    zlib1g-dev

# Install rbenv
RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv && \
    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc && \
    echo 'eval "$(rbenv init -)"' >> ~/.bashrc

ENV PATH /root/.rbenv/shims:/root/.rbenv/bin:$PATH

# Install ruby-build & ruby
RUN git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build && \
    ~/.rbenv/bin/rbenv install 2.5.1 && \
    ~/.rbenv/bin/rbenv global 2.5.1

# Initiarize ruby encording
ENV RUBYOPT -EUTF-8

# Install bundler
RUN ~/.rbenv/bin/rbenv exec gem install bundler -v 1.16.3
```

# やってること

### Require to install ruby

下記、ruby・rbenv のダウンロードおよびコンパイルに必要なモジュールのインストール。

+ git 
+ build-essential 
+ libssl-dev
+ libreadline-dev
+ zlib1g-dev

### Install rbenv

##### リポジトリからソースを落としてくる

git repository から clone してパスを通している。
https://github.com/rbenv/rbenv#basic-github-checkout

##### 明示的にパスを通す

`~/.bashrc` に書き加えただけだと GitLab CI で利用しようとしたときにデフォルトでパスが通らなかったので `ENV PATH ...` で明示的に指定している。

### Initiarize ruby encording

ruby のエンコーディングを **UTF-8** としている。
デフォルト だと **US-ASCII** になっており `bundle install` が動かなかった。

### Install ruby-build & ruby

また、 `docker build` している最中はインストール後でも rbenv のパスが通ってないので `~/.rbenv/bin/rbenv exec ...` みたいなノリでフルパスを指定しなければならなかった。。

業務都合でデフォルトの version は 2.5.1 としている。

### Install bundler

`bundle install` したかったので **bundler** をいれた。
**Gemfile.lock** の `BUNDLED WITH` の version と合わせる必要があったので version を固定にしている。

# 終わりに

このコンテナで社で負債になっている chef-repo を動かしたかったんだけどビクともしなかった（笑
rbenv/ruby-buildのアップデートをしたのに、rbenv install -l で欲しいversionが表示されない時の解決方法

## update
・rbenvのアップデート

```
$ brew update
```

・ruby-buildのアップデート

```
$ brew upgrade ruby-build
```
## インストール可能なrubyバージョンの確認

```
$ rbenv install -l
```

rbenv/ruby-buildをアップデートしたのにも関わらず、インストールしたいversionが表示されなかった。
（今回の私の場合、`2.5.3`が欲しかったのに表示が無かった）

## 解決方法
どうやらrbenvのpluginを更新する必要があるらしい。

```
$ cd /Users/yusaku/.rbenv/plugins/ruby-build && git pull && cd -
```

これで2.5.3が表示されるようになった。

```
$ rbenv install -l|grep 2.5.
  2.5.0-dev
  2.5.0-preview1
  2.5.0-rc1
  2.5.0
  2.5.1
  2.5.2
  2.5.3
  2.5.4
  2.5.5

```

## インストール

```
$ rbenv install 2.5.3
```

```
$ ruby -v
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-darwin17]
```

これでインストールできました。
iPhoneのバッテリーを長持ちさせるコツ・リチウムイオン電池は消耗品

私の勝手な偏見と都市伝説でリチウムイオン電池の長持ちさせるコツを誤解していたので、
Apple公式サポートやAnker公式の情報を見つつバッテリーを長持ちさせる方法を改めて調べてみました。

## iPhoneのバッテリー状態の確認

まずは、現在のiPhoneのバッテリーの状態を確認する（iOS11.3以降）

- 「設定」アプリ→「バッテリー」→「バッテリーの状態」

### 最大容量とは
iOS11.3以降でバッテリーの最大容量を確認できるようになっています。
リチウムイオンバッテリーの特徴として充電→駆動→充電のサイクルを繰り返すにつれ「化学的経年劣化」が発生します。
充電できるMAXの最大値が少しずつ劣化して減ってきているということです。

### ピークパフォーマンス性能
最大容量が90%以上にも関わらず

- シャットダウンが多発する
- バッテリーの減るスピードが急激に早くなった
- App の起動に時間がかかるようになった

などの症状がある方はここを確認します。

正常なメッセージ
![IMG_0466.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/a9d56e7c-4982-d47b-b63f-7f16ef9602e5.png)

ここのメッセージが上記以外の場合は
iOSのパフォーマンス管理（性能低下させる）機能が働いています。

バッテリーが劣化している場合もメッセージが変わりますので正常値でない場合はバッテリーの交換目安になります。


## バッテリーの耐用年数（寿命）を延ばす日常的なコツ。充電はどういうサイクルでした方がいいか？
では実際にどういう風に普段使っていけばいいのかを調べてまとめてみました。

### 最新のソフトウェアにアップデートする
よくiOSをアップデートしない人も見かけますがAppleのソフトウェアアップデートには
先進的な節電技術が含まれていることが多いのでアップデートを推奨されています
（まあリリース直後にアップデートすると不具合に合うこともあるので人柱にならないようタイミングは注意ですね）

### バックグラウント処理をオフにする

「設定」アプリ→「バッテリー」で、Appごとのバッテリーの使用状況を確認できます
ここでバックグラウンドで動いているアプリを確認できます。
日本語設定のiPhoneでは現在（背面処理）と表示されているようです。
ここで不要な処理が動いているアプリを確認し、
「設定」>「一般」>「Appのバックグラウンド更新」と選択し、
「Wi-Fi」「Wi-Fiとモバイルデータ通信」または「オフ」を選びます。
「オフ」を選ぶとアプリケーションのバックグラウンド更新を完全に止めることができます。

### コンピュータをコンセントにつなぎ、電源を入れてから、デバイスを充電する
> コンピュータを使ってUSB経由でiOSデバイスを充電する時は、そのコンピュータがコンセントにつながれており、電源が入っていることを確認してください。デバイスをつないだコンピュータの電源が切れている場合や、スリープモードまたはスタンバイモードになっている場合は、デバイスのバッテリーが消費されることがあります。

これはちょっと意外でした^^；

### 週１や定期的に電源を切る
> たまに休みが必要なのは、スマートフォンやタブレット等のモバイル機器も同じこと。定期的に電源を切ることで、バッテリーへの負担を軽減することができます。特に睡眠時間は、電源を切るチャンスです。できれば少なくとも週1回は電源を切ることをオススメします。

### 約20％ ～ 80％の間でバッテリー残量を維持する

定期的に100%から0％まで使い切ったほうが良いのか？
> リチウムイオン電池に関して言えば、これは誤りです。過度な振れ幅 (100%→0%) はバッテリーに不可がかかり、劣化に繋がります。バッテリーの性能を長く保たせるなら、約20％ 〜 80％でバッテリー残量を維持しましょう。

0%まで使い切らないほうがいいみたいですね; 完全に勘違いしてました。


参照
【知っているようで知らない、バッテリーの話】
https://magazine.ankerjapan.com/%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%82%88%E3%81%86%E3%81%A7%E7%9F%A5%E3%82%89%E3%81%AA%E3%81%84-%E3%83%90%E3%83%83%E3%83%86%E3%83%AA%E3%83%BC%E3%81%AE%E8%A9%B1
**↑ここ分かりやすくてオススメです**

Apple公式
https://support.apple.com/ja-jp/iphone/repair/battery-power

https://time-space.kddi.com/mobile/20180801/2394
https://appllio.com/iphone-battery-change-program-and-extend-useful-life
コマンドラインの基礎（入門）

コマンドラインについて学ぶには、[プロゲート](https://prog-8.com/)の「[Command Line 学習コース 基礎編](https://prog-8.com/lessons/commandline/study/1)」がおすすめ。
ここではそこで扱ったコマンド＋αを掲載する。



#コマンドラインを理解するための用語集

|用語名|意味|
|:-----------------|:------------------|
|ファイル|データのまとまり|
|ディレクトリ|ハードディスクなどの記録メディア上のファイルの保存場所|
|カレントディレクトリ|現在いるディレクトリ|
|ルートディレクトリ|最上位のディレクトリ|
|パス|ファイルまでの道筋|
|絶対パス|ルートディレクトリからファイルまで経由されるディレクトリを全て記述した道筋|
|相対パス|カレントディレクトリから指定のファイルまで経由されるディレクトリを全て記述した道筋|


#コマンド一覧

|コマンド（命令）|できること|
|:-----------------|:------------------|
|help|主要コマンドの確認|
|exit|コマンドラインの使用の終了|
|pwd|カレントディレクトリの絶対パスの確認|
|cd|ディレクトリの移動|
|mkdir|ディレクトリの作成|
|touch|ファイルの作成|
|mv|ファイルやディレクトリの移動、ファイル名やディレクトリ名の変更|
|rm|ファイルやディレクトリの削除|
|ls|ディレクトリの内容を確認
|tree|ディレクトリの内容をツリー表示で確認



#コマンド詳細

###help

使用例①：`help`

主要コマンドを確認する

---

###exit

使用例①：`exit`

コマンドラインの使用を終了する

---

###pwd

prin working directoryの略。

使用例①：`pwd`

カレントディレクトリの絶対パスを確認する

---

###cd

change directoryの略。

使用例①：`cd ディレクトリ名`

カレントディレクトリに存在するディレクトリへ移動する

使用例②：`cd ..`

カレントディレクトリの一つ上のディレクトリへ移動する

---

###mkdir

make directoryの略。

使用例①：`mkdir ディレクトリ名`

カレントディレクトリに新しいディレクトリを作成する

---

###touch

使用例①：`touch ファイル名`

カレントディレクトリに新しいファイルを作成する

---

###mv

moveの略。

使用例①：`mv ファイル名1 ファイル名2 ディレクトリ名`

カレントディレクトリにあるファイル1とファイル2を指定ディレクトリに移動する

使用例②：`mv ディレクトリ名1 ディレクトリ名2 ..`

カレントディレクトリにあるディレクトリ1とディレクトリ2をカレントディレクトリの一つ上のディレクトリに移動する

使用例③：`mv ファイル名1 ファイル名2`

カレントディレクトリにあるファイル1をファイル2という名前に変更する

---

###rm

removeの略。

使用例①：`rm ディレクトリ名`

カレントディレクトリにあるディレクトリを削除する

---

###ls

list segmentsの略。

使用例①：`ls`

カレントディレクトリの内容を確認する

使用例②：`ls ディレクトリ名1/ディレクトリ名2`

カレントディレクトリにあるディレクトリ1の中のディレクトリ2の内容を確認する

---

###tree

使用例①：`tree /F`

カレントディレクトリ以下の内容を全てツリー表示で確認する
vimの入門的なコマンド

#どんな人向け
+ vim初心者
+ **diff** とか **log** を閲覧する人
+ **CUI** 環境でちょっと編集したい人
+ 重いテキストを手軽に閲覧したい人

#基本コマンド
これを知っていればvimは一応操作できるだろうコマンド

| キー | アクション |
|:-:|:-:|
|h・j・k・l|←・↓・↑・→ カーソル移動|
| i | 文字入力モードへ |
|esc| ノーマルモードへ |
|  :wq |  変更を保存してvim終了 |
|:q!|変更を破棄してvim終了|

+ 焦って間違えて変更してしまったら **`esc`**  でノーマルモードにしてから **`:q!`** でvimを一度終了してやり直す
+ ノーマルモードへの移行は **`esc`** より **`control` + `[`** を使用するとスムーズ (な気がする

#閲覧によく使うコマンド

| キー | アクション |
|:-:|:-:|
| control + d  |  半ページ下へ移動 |
|  control + u |  半ページ上へ移動 |
|gg|一番上の行に移動|
|G|一番下の行に移動|
| /文字列 | 文字列を検索  |
|  n | 次の文字列を検索  |
|  N | 前の文字列を検索  |
+ 死ぬほど長い **log** を閲覧するときに必須なコマンド
+ **vimtutor** (vimのチュートリアルコマンド)で閲覧の練習してみると良い

#編集によく使うコマンド
| キー | アクション |
|:-:|:-:|q
|x|1文字削除|
|dd| 1行削除|
|u|一つ前の変更を戻す(Undo)|
| control + r  | Undoを取り消す(Redo) |
|.|一つ前にしたアクションをもう一度行う|
|v|ビジュアルモードへ|
|yy|コピー(ヤンク)|
|p|ペースト|
+ ちょっと編集として使うなら覚えた方が良いコマンド
+ ビジュアルモードは文字列を選択し、コピペ等に使えるモード

#おわりに
個人的によく使うコマンドだけ載せました:triumph:
他にもいろいろ探してみてください！

#参考文献様
[よく使う Vim のコマンドまとめ](https://qiita.com/hide/items/5bfe5b322872c61a6896)
[Vim初心者向け：Vimの使い方が分かるコマンド - "vimtutor"](https://qiita.com/y-temp4/items/3032d22cb5cc6ae3117a)
話題になっている技術系の記事を一瞬で把握できるページを作ってみた

「エンジニアにとって情報収集は命！」ということで、情報収集に関するツールを作ってみました。もっぱら自分用に作ったのですがせっかくなので公開してみます。

**[こちら](https://feed.kkty.jp)からアクセスできます。**

## できること

### 期間を指定して記事の一覧を取得

過去7日間/過去30日間/過去1年間に投稿された、技術系の記事を取得できます。はてなブックマークのブックマーク数の多い順（≒話題になった順）にソートされています。「もっと読む」ボタンでどんどん読み込めます。

<img src="https://storage.googleapis.com/kkty-assets/201907171403.gif" width="300"/>

### 検索ワードなどで絞り込み

上の検索ボックスにキーワードを入れることで絞り込みができます。

- OR検索ができます。「docker or kubernetes」と検索すると、"docker"または"kubernetes"をタイトルに含む記事の一覧を取得できます。「(A (B or C)) or D」みたいなことも一応できます（「BまたはCを含み、Aを含む」または「Dを含む」記事が取得できます）。
- ドメインを指定して検索することができます。「site:qiita.com docker」のようにすればqiita.com内の記事で、"docker"をタイトルに含むような記事の一覧を取得できます。

<img src="https://storage.googleapis.com/kkty-assets/201907171404.gif" width="300"/>

## やっていること

いくつかのRSSフィードを1時間おきに巡回しています。また、各記事について[はてなブックマークさんのAPI](https://b.hatena.ne.jp/help/entry/api)を利用させていただいて、ブックマーク数を取得しています（各記事に対して取得のインターバルは1日, 2日, 4日, ...のようになっています）。

## 利用スタック

- フロントエンドにはVue.jsを用いて、SPA的な感じにしています。
- バックエンドやデータ収集系のプログラムはNode.jsで動いています。
- データベースはMySQLを用いています。
- とりあえずはGCP Compute Engineのインスタンス上で動かしています。(Kubernetesなどに移したいのですが少しコストが嵩むので...)

---

[こちら](https://feed.kkty.jp/api/feeds)で巡回しているRSSフィードの一覧が見れるのですが、「これを追加したほうがいい！」などがありましたら教えていただけると幸いです。また、それ以外についてもご意見などいただけると嬉しいです。
Laravel 5.8 環境構築

# 環境構築

## 1.apache + php + Mariadb導入

```
sudo yum install httpd
sudo yum php72u
(require epel)
sudo yum mariadb
```

## 2.composerの導入

3.Laravel環境構築
laravelのプロジェクトを作る

```
cd /var/www/
composer create-project "laravel/laravel" hogehoge
````

## 3.apacheの設定
Directoryディレクティブにpublicを設定する

```conf.d/hoge-ssl.conf
<Directory "/var/www/hogehoge/public">
Options Indexes FollowSymlinks
AllowOverride all
Require all granted
</Directory>
```

## 4.サーバのパーミッション設定
[CentOS/Apache/Laravel使用時のpermission設定方法](https://qiita.com/Todate/items/d0d5c38f62621711a79b)参考。
一般ユーザ(ippan)とhttpdプロセスを同一グループにする。

```
cd /var/www/hogehoge
chown -R ippan:ippan ./
```

storageとcacheのグループだけ変更

```
chown -R :apache ./storage
chown -R :apache ./bootstrap/cache
```

ブラウザでアクセスするとLaravelの初期画面が表示される

# DB設定

## 5.Laravel 環境設定
環境設定は「.env」ファイル
.envファイルにない項目は./config/app.configの値が採用される

.envファイル
APP_KEY：暗号化・復号化に使用する（構築時に一回更新しておくだけでよいかも）
というか途中で変えると復号できなくなる

```
$ php artisan key:generate
```

DB_*がDB設定
DV_CONNECTIONの種類
mysql/sqlite/pgsql/sqlsrv

Database/databaseuser作成

```
$ mysql -u root -p 
mysql> create database hoge_db
mysql> GRANT ALL PRIVILEGES ON `hoge_db.*` TO 'hoge_admin@'localhost' IDENTIFIED BY 'hogepassword';
```

```[.env]
DB_DATABASE=hoge_db
DB_USERNAME=hoge_admin
DB_PASSWORD=hogepassword
```
Interior Designers in Cochin


Interior Designing Company in Kochi ensures 100% client satisfaction through their systematic working. It was one of the most notable <a href="http://paulinteriors.in/">interior designers in Cochin</a> developed with current mechanical offices and gathering experienced organizers. We are the most versatile creator of confined kitchen, eating regions, rooms and living locale. Our pros have shrewd contemplation and imitativeness with perfect workmanship to change your place to take after a wonder land. We are the best office internal parts in Kochi.Our white dividers and standard furniture design changes the entire condition off depleted working environments. Our point is to make incredible atmosphere to work the agents for the span of the day with pleasure. Shilpakala is the standard inside arrangement in Kerala. It was made by our confirmed fashioners. We fix flexible furnishings to suites the spot well.
![paul-interiors-home-10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407657/707c4dc7-47d3-1aed-fa75-f2c9f5ba5425.jpeg)
データベース　whereの扱い方

|    id    |    name    |   
|:---------|-----------:|
|    1     |     abc    |     
|    2     |     aaa    |       
|    3     |     ccc    |  
#条件（nameがabc）に当てはまるものを取り出す【基本】

```ruby 
①User.where(name: "abc")
②User.where("name = ?","abc")
#色々な書き方がある。（②の方は条件が複数の場合や複雑な条件の時に使用する。）
#両方id1が取得できる。
```

#条件（idが２以上）に当てはまるものを取り出す

```ruby 
User.where("id >= ?",2)
#id2と3が取得できる。
```

#条件に当てはまるのも以外を取り出す。

```ruby 
User.where.not(name: "abc")
#id2と3が取得できる。
```

#名前（User.name）に文字("a")が含む物を取り出す。

```ruby 
User.where("title like ?","%a%")
#id１と２が取得できる。
#likeで検索する。
#%は０以上の任意の文字列を表す。（"%a"）ならid2のみ取得となる。

```
Gitリポジトリ追加からの流れ

忘れるといけないのでリポジトリ追加から流れだけささっと。


①トップの *New repository* から進んで *Create a new repository* 画面へ

② *Repository name* 入力後、*Initialize this repository with a README* にチェック

③`/users/<name>/git`がなければGitのリポジトリを作る（または初期化する）ために`init`する必要がある。

```text:terminal
/users/sf213471118/git
$ git init
```

`/users/<name>/git/.git`が作られたことを確認する

```text:terminal
/users/sf213471118/git
$ ls -a
.		.DS_Store	.git
```

git直下に`/.git`というサブディレクトリが作られたらCommitに向けて`Clone`する。

--------------

④リポジトリを選択し *Clone or download* を押下したらアドレスをコピーする（SSHを使用）

アドレスの構成は以下の通り

```
[user] @ [host] : [Repository adress]
```

ターミナルで早速Clone

```text:terminal
/Users/sf213471118/git
$ git clone <user>@<host>:xxx/test.git
Cloning into 'test'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
$ cd test/
$ ls
README.md        /* リポジトリに格納してあるファイルが確認できた */
```

-----------

⑤試しに`README.md`を書き換える。

```text:README.md
# test

abcdef
~
~
```

------

⑥*Commit Log*に変更箇所を明示的に記録しておくために`add`する。

`add`のオプションは複数あるが、変更を全て適用する場合は `-A` or `--all` を使用（どちらでもOK）

```text:terminal
/Users/sf213471118/git/test
$ git add -A
$ git add --all
```

-----

⑦gitリポジトリにファイルの変更を保存するため`commit`する。

このとき`-m`を用いることで変更時のコメントを追加することができる。

```text:terminal
/Users/sf213471118/git/test
$ git commit -m "first commit"
[master 0226a81] first commit
 Committer: sf213471118 <xxx@xxx.xxx>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

 1 file changed, 7 insertions(+), 1 deletion(-)
```



----------

⑧ローカルリポジトリで変更した箇所をリモートリポジトリに`push`する。


```text:terminal
/Users/sf213471118/git/test
$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 266 bytes | 266.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: detect-secrets-stream (beta) ver=xxx-212s7c2b78321f0836d59e162s57975656hejskw FAQ: xxxx
remote: 
remote: Successfully send push metadata.
remote: Push info collect pre-receive hook finished within 3 seconds.
To <user>@xxxxx/test.git
   w412d92..9274q73  master -> master
```

この変更がリモート上で反映されているかをGitHubで確認する。
__file__を使用しても実行中のスクリプトのディレクトリ名を取得できない理由を調べる

# いきなり結論
>Pythonの``__file__``は、対話モードで実行するとエラーになる

　参考：https://takeg.hatenadiary.jp/entry/2019/02/06/085241

# きっかけ

↓↓の構文が何を表しているのかを知りたくてpython対話モード上で試したら
エラーを吐いて終了した。mnist.py上で実行したらうまくいったのに、、、なぜだろう…？
試行錯誤したらなんとなくうまくいったけど、何がどうおかしかったのか整理することにした。

```:実行に使用したプログラムの一部
dataset_dir = os.path.dirname(os.path.abspath(__file__))
save_file = dataset_dir + "/mnist.pkl"
```
ちなみ結論からいうと、python実行時の実行コンソールのカレントディレクトリ配下にある"mnist.pkl"をsave_fileに代入することを指す。
今回の場合、実行時は
/home/ec2-user/environment/deep-learning-from-scratch/dataset/mnist.py
から実行するので、そこと同じディレクトリにある
/home/ec2-user/environment/deep-learning-from-scratch/dataset/mnist.pkl
をsave_fileに代入することになる。

# 最終的にうまくいった構文
```
>>> print(os.path.dirname(os.path.abspath('__file__')))
/home/ec2-user/environment/deep-learning-from-scratch/ch01
```
これが基本、として以下の試行錯誤の歴史を振り返る。


# で、ここからしくじりの記録を確認
cloud9の実行コンソール上で試行錯誤した結果が残っているのでこれを眺めていく。
何がおかしいのかなぁ…

```
>>> print(os.path.dirname(os.path.abspath(__file__)))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined                    ←そもそもosモジュールをインポートしていない
>>> import os.path
>>> print(os.path.dirname(os.path.abspath(__file__)))　←よく見ると__file__をシングルクォート（'）で囲んでない
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '__file__' is not defined
```
ともかくどうやったらうまくいくのかを知りたくて調べたら↓↓にたどり着いた。
　https://qiita.com/opankopan/items/42a78754aa2fe6b6a29f
結果、なぜかうまくいった、って感じだった。まだピンと来ていない。
dir3はエラーがでているがsysモジュールをインポートしてないのが問題のようだ。今回は割愛。

```
>>> current_dir1 = os.path.dirname(os.path.abspath("__file__"))
>>> 
>>> current_dir2 = os.path.dirname(os.path.abspath('__file__'))
>>> 
>>> current_dir3 = os.path.dirname(os.path.abspath(sys.argv[0]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
>>> 
>>> print(current_dir1)
/home/ec2-user/environment/deep-learning-from-scratch/ch01
>>> print(current_dir2)
/home/ec2-user/environment/deep-learning-from-scratch/ch01
>>> print(current_dir3)print(os.path.dirname(os.path.abspath(__file__)))　←よくみるとprint(current_dir3)でいいのに余計なモノついてる
  File "<stdin>", line 1
    print(current_dir3)print(os.path.dirname(os.path.abspath(__file__)))
                           ^
SyntaxError: invalid syntax
```

↑は変数に一度格納しているが
print()で囲めばいいよね？ってことでやってみたらうまくいった。
ちゃんとカレントディレクトリ出てる

```
>>> print(os.path.dirname(os.path.abspath('__file__')))
/home/ec2-user/environment/deep-learning-from-scratch/ch01
>>> 
```

# 何が違ったのか？
違いは、シングルクォートで囲んだかどうか、の違いっぽい。
シングルクォートで囲む必要があるときとないときの違いってなんだろ？
## 成功したやつ

```
>>> print(os.path.dirname(os.path.abspath(__file__)))
```
## 失敗したやつ
```
>>> print(os.path.dirname(os.path.abspath('__file__')))
```
…出てきた！やっぱり同じことで悩んでる人がいるんだねぇ～よかった
https://takeg.hatenadiary.jp/entry/2019/02/06/085241
曰く、
>Pythonの``__file__``は、対話モードで実行するとエラーになる

だそうだ。
# まとめ
対話モードだと少し勝手が違うんだねぇ～

～めでたしめでたし～
CentOS7へOpenJDKをインストールする方法

# 目的
yumでインストールできなかったので、手動でインストールする方法を自身の備忘録として。

## 構成
- CentOS7.6

## OpenJDKをダウンロード
ダウンロード先はここ→http://jdk.java.net/
昨日まで11があったのに消えてる・・・
予めダウンロードしてある「openjdk-11.0.2_linux-x64_bin.tar.gz」を使おう。。。

## おまじない
```
$ yum -y update
```

## 移動＆解凍
- yumもwgetも出来ないので（何故だ！）、WindowsからCentOSのhomeにファイルを移動
- /usr/local/へ展開

```
$ tar xvzf ~/openjdk-11.0.2_linux-x64_bin.tar.gz -C /usr/local/
```

## alternativesコマンド使用してJavaを使えるようにする
- 既にJavaがインストールされているとき、「alternatives --config java」コマンド実行時複数表示されるので、使用したいJavaの番号を打ってエンター

```
$ alternatives --install /usr/bin/java java /usr/local/jdk-11.0.2/bin/java 1
$ alternatives --config java

1 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
*+ 1           /usr/local/jdk-11.0.2/bin/java

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:1
$ alternatives --install /usr/bin/jar jar /usr/local/jdk-11.0.2/bin/jar 1
$ alternatives --install /usr/bin/javac javac /usr/local/jdk-11.0.2/bin/javac 1
$ alternatives --set jar /usr/local/jdk-11.0.2/bin/jar
$ alternatives --set javac /usr/local/jdk-11.0.2/bin/javac
```

## 環境変数の設定

```
$ vi /etc/profile
以下を末尾に追加
JAVA_HOME=/usr/local/jdk-11.0.2
export JAVA_HOME
PATH=$PATH:/usr/local/jdk-11.0.2/bin
export PATH
```
```
読み込み
$ source /etc/profile
```
## 確認
```
$ java --version
openjdk 11.0.2 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
```
SPAでのOAuth2対応に関するAuth0ブログのまとめ

#### [Auth0.com - OAuth2 Implicit Grant SPA](https://auth0.com/blog/oauth2-implicit-grant-and-spa/)

Implicit Grantを非推奨とする[OAuth 2.0 Security Best Current Practice (Draft)](https://tools.ietf.org/id/draft-ietf-oauth-security-topics-13.html)について、既存のアプリや今後開発するアプリでどのように対応していくべきかが解説されている。

##### A More Detailed Summary

* これからSPAを実装する場合は、Best Practiceに従いAuthorization Code Grant + PKCEを使うべきである。
* Implicit Grantを実装している既存のSPAについては、既知の問題に対するセキュリティ対策がされているのであれば、ベストプラクティスへの対応は任意である。

##### The Implicit Grant

* Implicit Grantには、Redirect URIの不十分な検証、Referer・ブラウザ履歴からのアクセストークン漏洩、Token Injectionといった問題がある。
* これらの問題にはToken Injectionを除けば確立された対策方法があるため、正しく実装すれば安全であるが、[OAuth 2.0 Security Best Current Practice](https://tools.ietf.org/id/draft-ietf-oauth-security-topics-13.html)では実装不備によるセキュリティリスクを下げる別の手段が提示されている。

##### Renewing access tokens

* ブラウザは秘匿情報を安全に保管する機能を提供していないので、XSS等によりRefresh Token漏洩が起きやすく、SPAではClient Secretは露出するためRefresh Tokenの悪用が可能となる。
* Best Practiceでは、Refresh Tokenを安全に使うためにSender-Constraint Token（Token BindingもしくはMutual TLS）が推奨されるが、Token Bindingはブラウザがサポートする見通しがなく、Mutulal TLSは仕様に課題が残されている。
* Sender-Constraint Tokenが利用できない場合の受容可能な方式として、Refresh Token Rotationがあるが、トークンを共有するクライアントが複数あるときに問題となる。またToken RotationはMicrosoft、Google, Auth0ですらサポートされていない。
* Refresh Tokenを使わない方法として、非表示にしたiframeで`prompt=none`を指定してアクセストークンを再取得することもできるが、将来的にApple ITP2でiframeでのCookieアクセスが禁止され使えなくなる可能性がある。

##### Different SPA Topologies and Alternative Approaches

* Backendがあるのであれば、Frontend・Backend間の認証をSession Cookieで行い、トークン管理（もしくは取得のみ）を全てBackendで行うことで、Refresh TokenをFrontendで扱わないこともできる。（Cookieはブラウザによりオリジンの制御がされるため安全である。）
Hyper-V + Docker for Windowsでいまさらphp5.6

# やりたいこと
dockerにマウントしたディレクト上のソースをWindowsホストのIDEで開発したい
centos7にhttpd2.4+php5.6の構成をdockerで構築

## WSLインストール

## Windows StoreからUbuntuインストール

* docker client
* docker server指定

```bash
vi .bashrc

export DOCKER_HOST='tcp://0.0.0.0:2375'
```

## Docker for Windows インストール

* docker server
* https://docs.docker.com/docker-for-windows/
* Setting -> General -> Expose daemon on tcp://localhost:2375 without TLS オン
* Setting -> Shared Drives オン

# コンテナー作成

WSL Ubuntuでdocker run

```bash
docker run -d --privileged --name myapp -p 41080:80 -p 41022:22 -v /c/{git場所}:/var/www/html/myapp centos /sbin/init

docker exec -it myapp /bin/bash
```

* httpd

```bash
yum -y install httpd
```
* conf

```bash
vi /etc/httpd/conf/httpd.conf

AllowOverride All
```

* conf.d

```
vi /etc/httpd/conf.d/custom.conf

DocumentRoot "/var/www/html/myapp/app/webroot"
```

* php56

```bash
yum update
yum -y install epel-release
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum -y install --enablerepo=remi-php56 php php-mcrypt php-cli php-common php-devel php-gd php-mbstring php-mysqlnd php-opcache php-pdo php-pear php-pecl-apcu php-pecl-zip php-process php-xml php-imap php-xml php-ldap php-mssql

systemctl start httpd
systemctl enable httpd
```

* 確認
http://localhost:41080/phpinfo.php

# わかってます
Dockerfileやdocker-composeを利用することね。
data-*のオブジェクトデータの取得・設定

# 概要
- オブジェクトを入れていた[data-*]の値の取得と設定がわからなかった
- 結果段階的だった

# テスト用 HTML

```html
<div class="test" data-value='{"title":"text", "name": "alpha"}'>
</div>
```

# オブジェクトデータの取得・設定
1. 取得
2. 設定
3. HTMLへ反映

[data-*] の取得方法は色々あるので、調べてみるのが良いと思います。

```js
// data-value の取得
var data = $('.test').data('value');
// number: var number を追加
data.number = 200;
// data-value に追加
$('.test').attr('data-value', JSON.stringify(data));
```

# 注意点
- HTML に追加する時、```JSON.stringify()```を使ってあげないと、HTML側では[object] となってしまう
- ```$('.test').data('value', data)``` ではHTML側に反映されない
Kernel TLSをOpenSSLで有効にする

Linux 4.13より、Kernel内でTLS処理を行うKTLSが利用できるようになりました。

最新のOpenSSLではKTLSを利用できるので試してみる。

参考
- [kernel.orgのドキュメント](https://www.kernel.org/doc/html/latest/networking/tls.html)
- [PLAYING WITH KERNEL TLS IN LINUX 4.13 AND GO
](https://blog.filippo.io/playing-with-kernel-tls-in-linux-4-13-and-go/)

（TLS1.2のAES-128-GCMしか対応してない？）

## ビルド
デフォルトでは有効でないので、ビルドする。
KTLSに対応してないカーネルを使用している場合は、強制的に無効になってしまいます。

```
$ git clone https://github.com/openssl/openssl.git
$ cd ./openssl
$ ./config enable-ktls
$ make
```

## 確認
適当なサイトに接続し、`strace`を使って、setsockoptでktlsを有効にしていることを確認する。

```
$ LD_LIBRARY_PATH=. strace ./apps/openssl s_client -connect asnokaze.com:443 2>&1 |grep setsock
setsockopt(3, SOL_TCP, TCP_ULP, [7564404], 4) = 0
```

これでよいのかな。
Gitの使い方でつまづいたところの記録

# 概要
　Gitを使っていて、つまづいて、その後解決した方法をまとめていきます。
　また、忘れてしまうことも多いので、そういったものも自分用にまとめておきます。
　個人的なメモの側面が強い記事ですので、ご注意ください。

# 特定ブランチの現在ディレクトリにあるファイルを確認したい
　今いるブランチのディレクトリと同じ階層のファイルを閲覧したいなら、

`git show "ブランチ名":./"ファイル名"`

で閲覧できます。

# 特定コミットだけを別のブランチから取り出したい
### 失敗の流れ
　まずファイルが存在しているか確認として、

`git show "ブランチ名":"hoge/hogehoge/ファイル名"`

　でファイルの中身を見ました。
　そして、そのブランチにあるファイルを、今いるブランチに持ってこようとして、

`git checkout "ブランチ名" -- "hoge/hogehoge/ファイル名"`

　を実行しました。
　で、その時に出たエラーがこれです。

`error: pathspec 'hoge/hogehoge/"ファイル名"' did not m
atch any file(s) known to git`

　そんなファイルないと怒られてしまいました。

### 成功に必要だったもの

　さっきshowで見れたんだからあるだろうと思いました。が、どうやらこっちの場合は**パスがいらない**ようでして、単純に

`git checkout "ブランチ名" -- "ファイル名"`

　でよかったようです(同じ階層であることが条件っぽい)。

showではパス指定で閲覧できるのに、checkoutの方で同じパスを指定するとエラー吐かれるのは、すこしややこしいと思いました(2019/5/20)。



# ローカルブランチを削除したい
オプションとして、`-D`を利用します。

`git branch -D "ブランチ名"`

これでローカルに存在しているブランチを削除することができます。

# リポジトリのファイル・ディレクトリを削除し、リモートに反映させる
### 削除方法

`git rm "filename"`

でファイルの削除。

`git rm -r "dirname"`

でディレクトリごと削除。
ここで`-r`はrecursiveオプション、つまり、再帰的にその下のファイルディレクトリを削除する意味を持つようです。

### 削除ファイルをリモートへ反映したい
削除したらそのファイルないんだからコミットできないじゃないか、と思っていたけど、どうやら`git rm`を使用することで、削除した段階でファイルがaddされるのと同様の効果があるようです。
なので、削除結果を反映したいのであれば、削除した段階でそのまま、

`git commit -m "コメント"`

をして、

`git push`

すれば良いです。


# コミットを書き直したい
コミットメッセージ書いてた途中なのにコミットしちゃった、というような時は、`--soft`付きのリセットコマンドを使います。

`git reset --soft HEAD^`

`--soft`オプションをつけることで、それまでの変更内容を失うことなく、元に戻すことができます。
ROS2に関する基本情報:初級 -class style-

【[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)】
【[ROS2レクチャー:初級 -class style-](https://qiita.com/NeK/items/14db31ff784a0bfafe3d)】

【次:[ROS2プロジェクトの作成]】

[ROS2プロジェクトの作成]:https://qiita.com/NeK/items/067bc227f706d7b8a2f3


より詳細は[こちら](https://qiita.com/NeK/items/18ff9e9c443295d5d805)

# ROS2の構造
## 用語

<dl>
<dt>ノード:node</dt>
<dd>ROS2のサービスとしてpublisher/subscriber, service/client, parameterなどの機能を提供するもの．ひとつのnode内に複数の機能を提供することもある．</dd>
<dt>ターゲット:target</dt>
<dd>class化したnodeを組み込み，実行できるようにしたものをtargetと呼ぶ．ひとつのtarget内に複数のnodeを組み込むことも可であり，その場合nodeの実行順や並列動作などを柔軟に制御することもできる．</dd>
<dt>ライブラリ:library</dt>
<dd>nodeを共有ライブラリ化したもの．</dd>
<dt>パッケージ:package，プロジェクト:project</dt>
<dd>関係の深いターゲット，ライブラリを集めたもの．ros2 pkg createで簡単に作成できる．</dd>
<dt>ワークスペース:workspace</dt>
<dd>使用するパッケージを集めたトップディレクトリ．普通にmkdirなどで作成する．</dd>
<dt>アンダーレイ:underlayとオーバーレイ:overlay</dt>
<dd>ROS2が管理する領域．特に管理する全体の領域を<font color="Red">アンダーレイ:underlay</font>と呼び，source /opt/ros/&lt;distro&gt;/setup.bashで設定される．その中にworkspaceやpackageがある．
workspaceやpackageなど，切り替えて使用するもの/できるものを，アンダーレイに対して<font color="red">オーバーレイ:overlay</font>と呼ぶ．
</dd>
</dl>

# ROS2における実装方法
ROS2での実装スタイルを大別すると以下となる．

- ROS風node
- クラス化したnode
    - 初級 -class style-の説明対象
- 共有ライブラリ化したnode
- コンポーネント化したnode

## クラス化したnode
ROS2ではターゲットとnodeを分離することが推奨されている．これによりnodeの再利用を高めるとともに，一つのターゲットで複数のnodeを使用できるようになる(それにより実行順番など細かな制御も可能になる)．
nodeの実行はROS2システムのspin関数により制御されるので，クラスとしてはnodeの準備・設定についてのコードを書くことになる．標準的なプログラムでは，コンストラクタの中でほとんどの準備・設定を書くことになる．
```

![ROS2クラス化PG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284261/eafb4a29-3ac0-d54a-f06e-e85121e5a7aa.png)

【次:[ROS2プロジェクトの作成]】
超絶簡単！Clovaスキル開発

## はじめに
[少し前の記事](https://qiita.com/ufoo68/items/f0ba45347b226c8afcd8)のClovaスキルバージョンです。
使う言語やデプロイ環境は特に変更ありません。

---

## Clovaとは
[こちら](https://clova.line.me/)が公式サイトです。要はLINEが開発したスマートスピーカーに搭載されているAIアシスタントです。
Clovaには予め色々な機能が入っていますが、追加で追加で機能を搭載させることができます。その追加できる機能を**スキル**と呼び、私達も実際に開発することができます。

---

## Clovaスキルをつくるには
まずは[ここ](https://clova-developers.line.biz/#/)にアカウントを登録する必要があります。ここのデベロッパーサイトを使ってClovaのスキルを登録することができます。
また、開発したスキルが使える範囲は以下の２パターンになります。

- **所定の審査**を通過して公開することで一般ユーザーも使える
- 開発モードのまま自分のLINEアカウントに連携したClovaだけがスキルを使える


---

# スキルを作ってみよう

---

## まずはスキル設定
@sumihiro3さんの[この記事](https://qiita.com/sumihiro3/items/3ca0a2f849a116b509ff)がかなり丁寧に解説してくださってます。設定そのものは難しくないので特にこちらで別途解説する必要はないと思いますが、以下の２つについてはスマートスピーカー開発特有の要素なので次に解説します。

- インテント
- スロット 

---

## インテント
インテントはスキルの対話モデルを各意図ごとにClovaがカテゴライズするものです。
例えば食べ物か飲み物を注文する対話モデルを考えた時に**orderFood**と**orderDrink**という２つのインテントを定義したとします。
![インテント (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/55003fe5-edda-8c2f-b9a8-4aab00e7c5ca.jpeg)
ここではまだ具体的な注文内容は定義しません。

---

## スロット
インテントをClovaが受け取ったら今度は注文したいものは何かを確認します。この**注文したいもの**がここではスロットとして定義されています。例として**orderFood**に**food**というスロットを定義します。
![スロット.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/ddc4146f-5c6f-9885-b873-c24ba46b5dbf.jpeg)
このスロットの中に食べ物の名前を定義していきます。つまり、Clovaは**定義したインテントとスロット以外を処理することはできません。**

---

## スロットとインテントを繋げる

インテントの中にサンプル発話リストを設定することでClovaが認識すべき発話を定義します。例として赤字になっている単語をスロットとして登録します。
![サンプル発話.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209689/133e65cf-71ca-0297-f401-65f90e91f9aa.jpeg)
サンプル発話リストに含まれているフレーズをClovaが認識すれば**orderFood**インテントを受け取ることができます。

---

## 実装してみよう
以前に書いた記事が２つあります。具体的な実装の参考にしてみてください。

- [Clovaで「抵抗値換算」のスキルを作ってみる](https://qiita.com/ufoo68/items/f6b04e1ca89a931ca206)
- [Clovaで「日本酒診断」のスキルを作ってみる](https://qiita.com/ufoo68/items/0df3e1c3c9beb4d4faf8)

---

# スキルを公開してみよう

---

## 審査の注意点

- 代表サンプル発話
- 音声の揺らぎの対応
- 想定しない発話の考慮

---

## 代表サンプル発話

１つ目には必ず「ねぇClova、」をつける。これの「ぇ」が「え」になっただけでもリジェクトされるので正確に登録しましょう。サポートされている発話は以下です。

- ねぇClova、**を起動して
- ねぇClova、**を開いて
- ねぇClova、**に繋いで

---

## 音声の揺らぎの対応

Clovaはユーザーの発話内容を漢字入りの言葉として認識します。例えば「カレー」という言葉も発音の違いによって魚の「鰈」や全く違った言葉の「加齢」と誤認識してしまう場合もあります。こういった誤認識にも対応するために事前に**いくつかの同義語をスロットに定義**しておきます。
この音声認識の評価をしたい場合は、「対話モデルを編集」を開くと左下に「ダッシュボード」と「発話履歴」を切り替えるメニューがあります。音声認識には自分のアカウントで登録したClovaを使ってできます。

---

## 想定しない発話の考慮

想定していたストーリー内容とは異なった発話をユーザーがしてしまう場合もあります（例えば「はい」か「いいえ」しか用意していない質問に「どちらでもない」とい答えが来た時など）。この場合２つの対処方法があげられると思います。

1. 想定しない発話にも対応できるシステムに強化する
2. 最初もしくは途中の言葉の誘導でそういった発話をさせない

技術的には1が難しくなりますが、審査を通過するだけが目的の場合は2の方法でも問題ありません。

---

## 参考になる記事

@h-takaumaさんの[記事](https://qiita.com/h-takauma/items/3147b5df2b50f3858a26)も見てもらうととても参考になると思います。

---

# 最後に

---

## 人気の出るスキルを作る方法

私もよくわかりませんが、前に参加した[勉強会のまとめ](https://qiita.com/ufoo68/items/a0043262ea0078fefd19)を参照すると何か良い知見が得られるかもしれません（多分）。。。
ROS2レクチャー:初級 -class style-

[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)

# 項目

1. [ROS2に関する基本情報](https://qiita.com/NeK/items/cd88fa49747f2a8b8392)
- [ROS2プロジェクトの作成](https://qiita.com/NeK/items/067bc227f706d7b8a2f3)
- [ROS2最小構成プログラム](https://qiita.com/NeK/items/d98a20e1c93993e06b7a)
- [ROS2のpublisher/subscriber概要](https://qiita.com/NeK/items/bb21b9e24f89f3182d05)
    - ROS1 style，class style共通の情報
- [ROS2の最小構成subscriber](https://qiita.com/NeK/items/224595987212067f41db)
- [ROS2における時間管理・Rate系とTimer系](https://qiita.com/NeK/items/bcf518f6dd79f970bb8e)
    - ROS1 style，class style共通の情報
- [ROS2の最小構成publisher](https://qiita.com/NeK/items/3a123fadd8a574b14162)
- [ROS2独自メッセージの作成](https://qiita.com/NeK/items/26751b8ed12976ff977d)
    - ROS1 style，class style共通の情報
- [独自メッセージを用いたROS2 publisher/subscriber](https://qiita.com/NeK/items/cd00705f7e473f83ca44)
- [ROS2の最小構成service/client](https://qiita.com/NeK/items/9d15487d4853638394a3)
- [ROS2のparameter概要](https://qiita.com/NeK/items/556a38782ce65bb81340)
    - ROS1 style，class style共通の情報
- [ROS2の最小構成parameter](https://qiita.com/NeK/items/c7710827c1676487473a)
- [YAMLファイルによるROS2のパラメータ設定](https://qiita.com/NeK/items/15bf1e657d8d694592ed)
    - ROS1 style，class style共通の情報
今日のpython error TypeError: only length-1 arrays can be converted to Python scalars

プログラムちょい替え（6）pyhon sin 描画
https://qiita.com/kaizen_nagoya/items/2702bdf0b89b3d841921

で、さらに直そうとして次のようなプログラムにしてみた。

```python:sina.py
import matplotlib.pyplot as plt
import numpy as np
import math 

# データ生成
x = np.linspace(0, 3.2, 10)
y = math.sin(x)

# プロット領域(Figure, Axes)の初期化
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(133)

# 棒グラフの作成
ax.scatter( x, y)

# 水平線、垂直線を入れる
ax.axhline(0)

plt.show()
```
実行してみる。

```shell-session:macOS
$ python sin.py
Traceback (most recent call last):
  File "sin.py", line 7, in <module>
    y = math.sin(x)
TypeError: only length-1 arrays can be converted to Python scalars
```

ごめん。
Rails6 のちょい足しな新機能を試す54（exists? 編）

# はじめに

Rails 6 に追加されそうな新機能を試す第54段。 今回は、 `exists?` 編です。
Rails 6 では、`ActiveRecord::Base#exists?` メソッドが strong parameter を引数として取ることができるようになりました。

Ruby 2.6.3, Rails 6.0.0.rc1, Rails 5.2.3 で確認しました。Rails 6.0.0.rc1 は `gem install rails --prerelease` でインストールできます。

```shell
$ rails --version
Rails 6.0.0.rc1
```

今回は、 User データを登録したときに同じ名前のユーザーが既に登録されている場合と登録されていない場合でメッセージを変えるようにしてみたいと思います。

# プロジェクトを作る

まずは、いつものごとくプロジェクトを作ります。

```shell
$ rails new rails6_0_0rc1
$ cd rails6_0_0rc1
```

# User の CRUD を作る

User のCRUD を作ります。 カラムは name だけです。

```shell
$ bin/rails g scaffold User name
```

# controller にプライベートメソッドを追加する

UsersController にプライベートメソッド exists_message を追加します。

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  ...
  private
    ...
    def exists_message(user_params)
      if User.exists?(user_params)
        'There are same name users'
      else
        "You are the first user whose name is #{user_params[:name]}"
      end
    end
end
```

# UsersController#create メソッドを変更する

`UsersController#create` メソッドの notice を変更します。

```ruby:app/controllers/users_controller.rb
class UsersController < ApplicationController
  ...
  def create
    @user = User.new(user_params)
    notice = exists_message(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: notice }
    ...
  end
  ...
end
```

# マイグレーションの実行

```shell
$ bin/rails db:create db:migrate
```

# ユーザー登録して確認する

ブラウザからユーザーを登録します。
`Taro` という名前 (name) で登録し、もう一度、登録します。

1回目と2回目以降でメッセージが異なります。

## 1回目
![first.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/82a89e46-eb66-b526-7cbf-cf4b706533f0.png)


## 2回目以降
![second.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/822ddd30-cd3b-ae83-cf61-03cf9df4bfa5.png)


# コンソールのログを確認する

コンソールのログを確認するとSQL文が適切であることがわかります。

```
  User Exists? (1.5ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" = $1 LIMIT $2  [["name", "Taro"], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:77:in `exists_message'`
```

# Rails 5 では

何度やってもメッセージは、

> You are the first user whose name is Taro

となります。 発行されているSQL文も strong parameter の name が使われていません。

```
  User Exists (1.2ms)  SELECT  1 AS one FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", nil], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:77
```

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try054_exists_accept_strong_params


# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Allow strong params in ActiveRecord::Base#exists?](https://github.com/rails/rails/pull/34891)
ローカルで始めた開発をリモートリポジトリにプッシュする



# 前提
会社でも個人開発でも、まだリモートリポジトリを作っていなくて、先にローカルPCで作り始めちゃおう！！！！みたいなことありますよね。
で、良いところまで進んで、「あれ？？ローカルだったっけ？やべー、リポジトリまだ作ってねえ、どうやるんだっけ」な方向けの記事です。


## 1. リモートリポジトリをサイトで作成する
あなたが何のウェブ型リポジトリマネージャーを使っているかわからない（github? gitlb? bitbucket?）けど、どれも大体リポジトリの作成は一緒なはず！
適当に作ってみよう！

## 2. SSHキーを作成する

次にやることはSSHキーの作成だ。
`git clone https://user-name@bitbucket.org/test/tekitou_repository.git`
とかHTTPで`git clone`したり`git push`しても良いんですが、ちょっとダサいし、
PCを再起動するたびにパスワード入れないといけないのがだるいので
SSHで`git clone`, `git push`等した方がいいです！

そもそもSSHを知らない人は適当に調べてください。
（僕も完璧に説明できるかって言われると怪しいので誰か良い記事あったらURL教えてくだしあ）

とりあえず下にコマンド書きます。
### sshキー作成して登録
```bash

cd ~/.ssh
ssh-keygen -t rsa -C “”
```

`-t` 暗号の種類
`-C` コメント

オプション知りたい方はこちら↓
https://euske.github.io/openssh-jman/ssh-keygen.html
https://qiita.com/notkzk/items/919dc7123924c87d9d3f


### 公開鍵をサイトに登録
各サイトの設定から適当に登録してください

### .ssh/configを作成して、設定を記述する

```bash

cd ~/.ssh
vi .ssh/config
```

```~/.ssh/config
Host bitbucket.org
  User git
  Port 22
  HostName bitbucket.org
  identityFile ~/.ssh/ainosh
  TCPKeepAlive yes
  IdentitiesOnly yes
```

#### 余談
仕事と個人開発で、アカウント分けてssh接続したい時（今後使うかもしれないですね）
[[備忘] 複数Githubアカウントでssh接続設定(config)を使い分ける手順](https://qiita.com/yampy/items/24638156abd383e08758)

## 3. 作業してたディレクトリでとりあえずgit初期化
```bash

git init
```
初期化っていうと、ちょっと身が竦むかもしれないけど、「ここをgit支配下にするよ！！」的な呪文だから大丈夫！！！！
何回`git init`しても大丈夫なので、ここで耐性をつけるために100回コマンドを打ちましょう！！！！（嘘）

## 4. リモートリポジトリにpushしていく

### まずはgit remote addで、origin=リモートリポジトリにしてあげましょう

```bash

git remote add origin git@bitbucket:user/tekitou_repogitory.git
```

### originが登録できたか確認
```bash
git remote -v
```

こんな感じででるはず

```
origin	git@bitbucket:user/tekitou_repogitory.git (fetch)
origin	git@bitbucket:user/tekitou_repogitory.git (push)
```

### 現状のソースコード確認
ローカルで色々作成していたファイルたちが見えるはず
まだstagingになってない
[Gitのステージングエリアについて理解する[Git]](https://qiita.com/takuyanin/items/8d5226fd5834e6ebc564)

```bash

git status
```

### git addしてcommit

#### 遷移
作業ディレクトリ --(add)--> staging area --(commit)--> (ローカル)gitリポジトリ --|超えられないローカルとリモートの壁|--(push)--> (リモート)gitリポジトリ
大体こんな感じです、わかってる人は飛ばしてください

ということでadd

```bash

git add .
git status
```
staging（）に上がってるはず


お次はcommit

```bash

git commit -m “initial commit”
git status
```

ローカルのgitリポジトリにcommitされて、綺麗になってます


### リモートリポジトリにpushする
準備は整ったので、pushします！
これでローカルで始めてしまった開発コードをリモートにプッシュできます！

```bash

git push origin master
```

もし、ここでエラー起きたら（例えばリモートのリポジトリ作成時にREADME作ってしまって、ローカルにはなくてだめ的な）

```bash

## このコマンドで差分をそのまま別のブランチに移しちゃいます
git checkout -b develop(ここは適当なブランチ名で良い)
## ブランチが見事にdevelopになってるはず
git branch
## ローカルのdevelopブランチをリモートリポジトリにプッシュしましょう
git push origin develop
```
あとはリモート側でマージしちゃえばおk

終了
Python+Anaconda環境でスクレイピングのテスト

Python+Anaconda環境でWebスクレイピングのテストコードを走らせるまでのメモ

##Beautifulsoupのインストール
`conda install beautifulsoup4`
※pipインストールと一緒
##サンプルコード
```python:scraping.py
import requests
from bs4 import BeautifulSoup
import re

target_url = 'https://www.yahoo.co.jp/'

result = requests.get(target_url)
data_soup = BeautifulSoup(result.text, 'lxml')
elements = data_soup.find_all(href=re.compile("news.yahoo.co.jp/pickup"))
for e in elements:
    print(e.getText() + '\n' )
```
###結果のサンプル
梅雨明け カギを握る台風5号
日韓関係悪化 歴史的転換点か
息子の叫び 体罰から救った親
高級車 大阪経由で北へ密輸か
ディーン&デルーカ 米で苦境
異常事態 高安休場で大関不在
こんまり 米エミー賞候補入り
訃報発表 流されたSMAP映像

## 参考
https://qiita.com/itkr/items/513318a9b5b92bd56185
mysql-connector-pythonの更新(特殊例)


今回はpython3で
mysql-connector-python-rf==2.2.2を利用していて
mysql-connector-python==8.0.16に乗り換えた話。


## mysql-connector-pythonの知識は参考サイトが良い
すごく参考になりました。感謝。
[Python3でMySQL Connectorのインストール・接続方法【快適に使う方法を紹介】](https://basicincome30.com/python3-mysql-connector)

### 乗り換えにあたり躓いた点を紹介

>$ pip install mysql-connector-python==8.0.16 //←先に新しい方をインストールしてしまった
>$ pip uninstall mysql-connector-python-rf

上記コマンドを実行した後、
`import mysql` がうまく実行出来なかった。
内部の挙動は把握してないが、多分リンクの切り替えが出来てないとかだろうと予想。

> // requirements.txtでインストールしたパッケージを全部アンインストール
> $ pip uninstall -y -r requirements.txt

これで解決した。

## 関係ないけど得た知識

> // 依存関係のチェックコマンド
> $ pip check

> // インスールしているパッケージ一覧
> $ pip list -o
laravel created_at,updated_atのdateのみ取得する方法

## サンプルコード

```
    public function toArray($id)
    {
        return [
            'id'=>$this -> id,
            'title'=>$this -> title,
            'body'=>$this -> body,
            'tag'=>$this -> tag,
            'seo_title'=>$this -> seo_title,
            'meta_description'=>$this -> meta_description,
            'featured_image'=>$this -> featured_image,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }

}
```

上記なようなコントローラー作成してgetしてしみると


```
{
    "data": {
        "id": 2,
        "title": null,
        "body": null,
        "tag": null,
        "seo_title": null,
        "meta_description": null,
        "featured_image": "https://headlesscms-api.s3.ap-northeast-1.amazonaws.com/test/BBjbX0ocpy3oWVGl5z05zRNzS9FoALqhmkJo1xKv.png",
        "created_at": {
            "date": "2019-07-15 01:40:07.000000",
            "timezone_type": 3,
            "timezone": "UTC"
        },
        "updated_at": {
            "date": "2019-07-15 01:40:07.000000",
            "timezone_type": 3,
            "timezone": "UTC"
        }
    }
}
```

`created_at`,`updated_at`に`"timezone_type"`,`"timezone"`がついてしまいます。

## dateのみにしたい時

### Carbonを使う
>CarbonとはPHPのDateTimeクラスをオーバーラップした日付操作ライブラリです。



```
<?php

namespace App\Http\Resources;

use \App\Post;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\Resource;

class ApiPostsCollection extends Resource
{
    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array
     */
    public function toArray($id)
    {
        return [
            'id'=>$this -> id,
            'title'=>$this -> title,
            'body'=>$this -> body,
            'tag'=>$this -> tag,
            'seo_title'=>$this -> seo_title,
            'meta_description'=>$this -> meta_description,
            'featured_image'=>$this -> featured_image,
            'created_at' => (new Carbon($this->created_at))->toDateTimeString(),
            'updated_at' => (new Carbon($this->updated_at))->toDateTimeString(),
        ];
    }

}
```

```
use Carbon\Carbon;
```

```
'created_at' => (new Carbon($this->created_at))->toDateTimeString(),
'updated_at' => (new Carbon($this->updated_at))->toDateTimeString(),
```

上記のようにCarbon使用したdateのみ返せるようになります。

```
{
    "data": {
        "id": 2,
        "title": null,
        "body": null,
        "tag": null,
        "seo_title": null,
        "meta_description": null,
        "featured_image": "https://headlesscms-api.s3.ap-northeast-1.amazonaws.com/test/BBjbX0ocpy3oWVGl5z05zRNzS9FoALqhmkJo1xKv.png",
        "created_at": "2019-07-15 01:40:07",
        "updated_at": "2019-07-15 01:40:07"
    }
}
```
headコマンド

`head`はファイルの中身を指定行だけ参照できる。（`cat`の軽い版？）

```
$ head [option] [filename]
```
これだけ。デフォルトで10行表示。

```
#普通に表示
$ head hoge.rtf

#パス指定
$ head /test/hoge.rtf

#拡張子指定
$ head *.rtf
```

複数の表示も可能。スペースで繋ぐだけ。

```
$ head hogehoge.rtf huga.py
```

行数の指定はoptionで指定。（文字数指定等のoptionも存在しているが使わなそう...?）

```
#行数指定
$ head -n 3 hogehoge.rtf       /*  3行のみ出力  */

#'n'option使わずにこれでもOK
$ head -3 hogehoge.rtf       /*  3行のみ出力  */
```

`xargs`で検索拡張。

```
#現階層におけるrtfファイルの中身に'2'が含まれるもの
$ find . -name "*.rtf" | xargs head -n 2

#これでも同義
$ find . -name "*.rtf" | xargs head -2


#上記の条件に'-L'optionで1ファイルごとの確認を追加
$ find . -name "*.rtf" | xargs -L1 -p head -n 2
```
ESP32のチップ情報を取得する（ESP-IDF）

ESP32のチップを判定する必要があったのでその方法をメモしておきます。

ESP-IDFでの例になります。

# Chipの取得

```#include "soc/soc.h"```

```
    uint32_t _chipmacid =REG_READ(DR_REG_EFUSE_BASE+12);

    char str[30];
    sprintf(str, "_chipmacid:%u\n", _chipmacid);
    console_print(str);

    uint8_t pkg = (_chipmacid >> 9) & 0x07;
    sprintf(str, "pkg:%u\n", pkg);//これがChipID
    console_print(str);
    // 0: "ESP32D0WDQ6",
    // 1: "ESP32D0WDQ5",
    // 2: "ESP32D2WDQ5",
    // 5: "ESP32-PICO-D4",
```

これでチップの判定をすることができます！
ウィルスバスターのスマートスキャンエージェントのバージョンを取得する

# はじめに

[ウィルスバスター](https://www.trendmicro.com/ja_jp/forHome/products/vb.html)([(C) Trend Micro](https://virusbuster.jp/vb/trial/sem/three_appeal_vb_aw.htm?AAID=ad_mem_GGL_vb_b_aw_004_190410_G1&gclid=CjwKCAjw67XpBRBqEiwA5RCocY0yTFfcvtY-woReGUyCPQoT96fC4wYerqjk9qiqf9adIDaXZEFh-RoCR_UQAvD_BwE))でファイルのウィルスキャンを行うに当たり、スマートスキャンのパータンファイルのバージョンを確認するために、VBScriptをnode.jsで動作させるアプリを作ったのでアップします。
業務で利用できます。

# 前提

* OS : Windows7以上
* PoweShellのターミナルで実行
* VSCodeでコード編集
* node.js環境構築済み

# Windows レジストリよりスマートスキャンバージョンを取得する
## getregvalue.vbs

- keysのHKLM、HKEY_LOCAL_MACHINEの省略。
- Echoでstdoutに取得した値を出力します。


```VBScript
Option Explicit
On Error Resume Next

' (c) Trend Micro SmartScanAgentPatternVersion

Dim objShell
Const keys = "HKLM\SOFTWARE\TrendMicro\UniClient\1700\Scan\SmartScanAgentPatternVersion"

Set objShell = WScript.CreateObject("WScript.Shell")
If Err.Number = 0 Then
    Wscript.Echo objShell.RegRead(keys)
Else
    Wscript.Echo  "エラー: " & Err.Description
End If

Set objShell = Nothing

```

# VBSCriptを動かすJavaScript
## getregvalue.js

- //Nologoでcscriptのロゴ出力を抑止します。
- あえて、console.logを使用しないで、process.stdout.writeで値を出力（改行抑止）
- getregvalue.vbsはこのgetregvalue.jsと同じでディレクトリにあること。

```JavaScript
    var spawn = require("child_process").spawn;

    var  proc =  spawn('cscript.exe',['//Nologo ./getregvalue.vbs'], { shell: true },(err,stdout,stderr) => {
        if (err) { console(err) }
    })

    proc.stdout.setEncoding('UTF-8');
    proc.stdout.on('data', (data) => {
        process.stdout.write(data.toString())
    });
```

# 実行結果

## 本日 2019/07/17

```Shell
PS C:\Users\～> node getregvalue.js
15.237.00
```
![2019-07-17-11-59-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239597/50fcfa06-4276-ba45-dad7-a3d10d1ca22b.png)

# まとめ

日々業務でファイルのウィルススキャンの実行結果のエビデンスを作成するので、ウィルスバスターのメニューからバージョンを確認する手間を省くために作成しました。
つまらないものですが、以外と便利です。

# 付録 ( 2019/07/24 追記 )

取得したウィルスパターンバージョンを利用するサンプルコードを追加します。

* Promise & resolveでバージョンを返却します。

```JavaScript
function GetRegVal() {
  const spawn = require("child_process").spawn;
  return new Promise((resolve,reject) => {
      let proc   =  spawn('cscript.exe',['//Nologo ./getregvalue.vbs'], { shell: true }, (err, stdout, stderr) => {
          if (err) { console(err) }
      })

      proc.stdout.setEncoding('UTF-8');
      proc.stdout.on('data', (data) => {
        resolve(data.toString());
      })
  })
}
```

* .then((戻り値) => { コーディング内で戻り値を参照します。 };

```JavaScript
   GetRegVal().then((pattern) => { 
       // ここに patternを利用したコードを記述します
       console.log(pattern);
   })
```
Unable to revert mtime: /Library/Fonts。今日のpython 警告　


matplotlibでのプロットの基本
https://qiita.com/KntKnk0328/items/5ef40d9e77308dd0d0a4

```sin.py
import matplotlib.pyplot as plt
import numpy as np

# データ生成
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)

# プロット領域(Figure, Axes)の初期化
fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(131)
ax2 = fig.add_subplot(132)
ax3 = fig.add_subplot(133)

# 棒グラフの作成
ax1.bar([1,2,3],[3,4,5])
ax2.barh([0.5,1,2.5],[0,1,2])
ax3.scatter(y1, y2)

# 水平線、垂直線を入れる
ax3.axhline(0.45)
ax3.axvline(0.65)

plt.show()
```
編集して実行してみる。


```shell-session:macOS
$ vi sin.py
$ python sin.py
Unable to revert mtime: /Library/Fonts
/Users/administrator/.pyenv/versions/anaconda3-4.3.0/lib/python3.6/site-packages/matplotlib/font_manager.py:280: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.
  'Matplotlib is building the font cache using fc-list. '
```

![sinpy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/603021d1-e09a-120b-f9a6-e7fa20716478.png)

けいこくは警告。
描画にすこし時間がかかった。

画像を閉じるとプログラムが終わった。再度実行した。

```shell-session:macOS
$ python sin.py
```

今度は警告が出なかった。さいしょだけなんだ。

# 参考資料

python error collection

https://qiita.com/kaizen_nagoya/items/4b13c6c9574c44931943

# 文書履歴(document history)
ver. 0.01 初稿 　20190717
ver. 0.01 初稿 　20230311
### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
Qumicoのドキュメントを作る方法

先日 組込Deep Learning向けのフレームワーク Qumicoが公開されました。

https://github.com/PasonaTech-Inc/Qumico/

readmeも何もないので困りますね。
mkdocsを使ってドキュメントを作る方法です。

まずはmkdocsをインストールしましょう。

```
pip install mkdocs
pip install mkdocs-material
pip install pygments
```

次にgit cloneしたディレクトリの下のdocsへ移動し、mkdocsをつかってドキュメントを作成してください。

```
cd docs
mkdocs build
```
siteディレクトリにindex.htmlが作成されるので、そこからブラウザでドキュメントを見てください。

Happy Hacking!
Spring Bootでバリデーション結果を取得する

Spring BootでFormのバリデーション結果を取得する方法

Form

@Data
public class SampleForm {
　@NotBlank
　@Size(max=100)
　private String str;
}


BindingResultをControllerのメソッドの引数として宣言し、hasErrorsメソッドの戻り値がtrueのとき
Formのバリデーションエラーが発生したこととなる。

Controller

@Controller
public class SampleController {
　@RequestMapping(value = "/Sample", method = RequestMethod.POST)
　　public String sample(@Validated @ModelAttribute SampleForm form, BindingResult bindingResult, Model model) {
　　　if (bindingResult.hasErrors()) {
　　　　List<String> errorMessage = new ArrayList<>();
　　　　List<FieldError> errorList = bindingResult.getFieldErrors();
　　　　for (FieldError error : errorList) {
　　　　　String field = "";
　　　　　if (StringUtils.equals(error.getField(), "str")) {
　　　　　　field = "入力文字列";
　　　　　}
　　　　　if (StringUtils.equals(error.getCode(), "NotBlank")) {
　　　　　　errorMessage.add(field + "が入力されていません");
　　　　　} else if (StringUtils.equals(error.getCode(), "Size")) {
　　　　　　errorMessage.add(field + "の桁数が範囲外です");
　　　　　}
　　　}
　　　model.addAttribute("errorList", errorMessage);

　　　return "sampleHtml";
　　}
　}
}
Rails内の時刻を一時的に変更する方法

## 概要
- 自分達のテストデータ作成用に制作フローを１発で全て実行する専用ページを作成することになった  
- バリデーションなどを正常に通すため(今日以前の日付を設定するとエラーになる)、また本番と同じフローを辿るために（バッチの実行曜日が決まっている）、任意のタイミングで時刻を変更したい  
- timecopを使えば任意のタイミングで任意の日時にサーバの時刻を変更できた

## 環境
- ubuntu - 16.04.4 LTS  
- rails - 5.0.7.2
- timecop - 0.9.1

## 方法
※注意：gemの導入、専用ページへのルーティングは開発環境に限定して実行し、上手くいったものであり、もしこの記事の内容を実行して何かあっても責任は負わない。あしからず。

timecopのgithub
https://github.com/travisjeffery/timecop

timecopを導入後、`Timecop.travel(t)`で`t`の日時にサーバー時刻を設定でき、`Timecop.return`で元の時刻に戻せたので今回はそれを使った。

```ruby:test_controller.rb
# 例
def create
  Timecop.travel(t) # 時刻をtに変更
  # ここでバッチやら処理を実行(この中でさらにTimecop.travelを使っても問題はない)
  Timecop.return # 時刻元に戻す
end
```