OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerの用語は大体「遊戯王カード」で置き換えられることを発見しました！

# 「本当に理解していれば、誰にでもわかるように説明できる」
Docker について自分が本当に理解できているのか？
それを確認するために「Dockerっておいしいの？」な少年にも概要を説明できる説明を考えていました。

表題通りたどり着いたのが「遊戯王カード」です！！

#### 前提
僕の遊戯王カードの理解は20年前くらいで止まっています。「サンダーボルト」や「昼夜の大火事」を3枚デッキに入れてたけれど、どうやら「禁止カード」？なるものが出てきたんですね～、程度の知識なので細かい部分は気にしないでください。

また、説明する範囲は「Docker」関連のみです。（k8sなどオーケストレーション含まない）
より突っ込んだ内容は今後「青年向けver.」とか考えていきたいです。。

# とりあえず結論となる図
**これが遊戯王カードの一般的な用語として、、**
![カードのワードイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/427f6d11-c086-7e3b-6f00-df279ecaad35.png)


**最終的に下の言葉で置き換えます。**
![dockerおきかえ拡大.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/b007a389-22a4-8a58-ddd2-7cd22b35ac51.png)


# 各ワードの対比　"遊戯王カードのワード" → "Docker 関連のワード"

| 遊戯王カード          |     Docker 置き換え  |   
|:---------------------:|:------------------:|
| カード          |            Docker Image |   
| デッキ            |              Docker Hub (repository)  |   
|  ドロー         |              docker pull コマンド |        
| 手札               |                ローカルに pull した Image |        
| 召喚             |             Image からコンテナを起動 |   
| フィールド          |           起動しているコンテナたちがいる場所 ( docker ps ) |
| 墓地          |           停止したコンテナたちがいる場所 ( docker ps -a ) |

### "カード" →　" Docker Image "
モンスターや魔法カードをデュエルで使うにはカードを手に入れなければなりません。
コンテナを起動（召喚）するにも Docker Image が必要になります。

### "デッキ" → "Dokcer Hub (repository)" 
自分が持っているカードを山積みにしたデッキはドローして手札に加えなければ使えません。
Docker Image もリモートの保存場所から直接起動させることは基本的にできません。

### "ドロー" → "docker pull コマンド"
真のデュエリストは狙ったカードをデッキからドローできるらしいですね。
使いたいコンテナを起動するため、リモートからローカルへドローしましょう。こちらは誰でもv" docker pull " で狙って引けます。

### "手札" → "ローカルに pull したイメージ"
起死回生のカードをドローできました！思わず顔がにやけます。
" docker images " コマンドで起動できるImage（カード）を確認します。

### "召喚" → "Image からコンテナを起動"
いよいよ召喚です。アニメではカードを場に出すと、ホログラムでモンスターが飛び出してきますね。
" docker run " コマンドで起動（召喚）してやりましょう。

### "フィールド" → "起動中のコンテナがいる場所"
場に出したカードは破壊されない限り、フィールドに居座り続けます。
起動しているコンテナは " docker ps " で確認しましょう。ここに表示されている限りは活躍してくれます。

### "墓地" → "停止したコンテナが送られる場所"
相手にカードを破壊されました。なにしてくれてんねん。。墓地へ送りましょう。
" docker kill " でコンテナを kill して墓地に送ります。 " docker ps -a " オプションで確認できるこのコンテナたちは、もちろん死者蘇生で再び場に出すことも可能です。

# 他にも無理やりだけど考えてみたもの

### "融合" → " docker-compose.yml "
特定のカードを組み合わせるとより強力なカードに！
" docker-compose up " コマンドで融合モンスター召喚！

### "オリジナルカード" → "Dockerfile の編集"
「僕の考えた最強のカード」を実際に作ってしまおう！名前を決めて、効果を決めて、ビジュアルを決めて、、
" Dockerfile " に自分の好みの環境を書き込んで、 build すれば完成。でもちゃんと規格に沿ったものじゃないとだめだよ。


# 今度は姪に Docker の素晴らしさを教えたい..
女の子は何が好きなんだ？
Rspec使い方   

## ①gemファイルにrspecのgemファイルの記述をする
` gemfile `
`gem rspec-rails`

## ②gem　ファイルのインストール
` bunlde install `

## ③rspecファイルのインストール
`bundle exec rails g rspec:install`
ここでいくつかファイルが生成される

```rb
create  .rspec
create  spec
create  spec/spec_helper.rb
create  spec/rails_helper.rb
```

## ④ テストコードを書くためのrspecのモデルを作る
`bundle exec rails g rspec:model User`
rspecのuserモデルが作られた

```rb
create  spec/models/user_spec.rb
```
## ⑤user_spec.rbにテストを記述する
まずはテストを書いてから、次にmodelファイルの中の該当のファイル（ここではuser.rb）を記述する
Java PDFファイルをSVGに保存する

Free Spire.PDF for Javaは、PDFをSVGに変換することをサポートしています。ここでは、以下の3つの態様から詳細に紹介します。
<ul>
<li>PDFからSVGまで</li>
<li>最初のPDFページをSVGに変換するだけです</li>
<li>マルチページPDFを1つのSVGに変えてください</li>
</ul>
使用ツール：[Free Spire.PDF for Java] (https://www.e-iceblue.com/Introduce/free-pdf-for-java.html) （無料版）

Jarファイルの取得と導入:

方法1：ホームページを通じてjarファイルのカバンをダウンロードします。ダウンロード後、ファイルを解凍して、libフォルダの下[Spire.Pdf.jar] (https://www.e-iceblue.com/Download/pdf-for-java-free.html)ファイルをJavaプログラムに導入します。

方法2：[maven倉庫] (https://www.e-iceblue.com/Tutorials/Licensing/How-to-install-Spire.PDF-for-Java-from-Maven-Repository.html) 設置による導入。

PDFからSVGまで

```java
import com.spire.pdf.*;

public class PDFtoSVG {
    public static void main(String[] args) {
        //Load the PDF file
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("Sample.pdf");
        //Save to SVG image
        pdf.saveToFile("Output/ToSVG.svg", FileFormat.SVG);
        pdf.close();
    }
}
```
![PDF to SVG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/35de0451-0a83-14a1-3c88-dd8066ceedb7.png)

最初のPDFページをSVGに変換するだけです

```java
import com.spire.pdf.*;

public class PDFtoSVG {
    public static void main(String[] args) {
        //Load the PDF file
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("Sample.pdf");
        //Only convert the first PDF page to SVG image
        pdf.saveToFile("Output/FirstPageToSVG.svg", 0,0,FileFormat.SVG);
        pdf.close();
    }
}
```
![First page to svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/639a40e4-86b4-b9b7-cd67-683af96a106a.png)

マルチページPDFを1つのSVGに変えてください

```java
import com.spire.pdf.*;

public class PDFtoSVG {
    public static void main(String[] args) {
        //Load the PDF file
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile("Sample.pdf");

        //convert a multipage PDF to one SVG
document.getConvertOptions().setOutputToOneSvg(true);
        pdf.saveToFile("Output/PDFtoOneSVG.svg",FileFormat.SVG);
        pdf.close();

```
![PDF to One SVG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/99adc0e8-8fb7-ea8e-ff47-485e160cc104.png)
【コピペ】オンプレミスからS3へのバックアップシェル

# 前提
## 目的
サーバデータの定期バックアップ

## 手法
- バックアップ先
    - S3
- データ
    - zip化
- 間隔
    - cron
- 過去分
    - 指定個数だけ保持
    - それ以上のものは自動で削除

# 準備
## aws側
### awsの認証情報の作成
- セキュリティ認証情報
    - サーバからS3へアクセスするために必要
    - [発行URL](https://console.aws.amazon.com/iam/home?#/security_credential)
    - 再発行不可能

### S3に保存場所を作成

## サーバ側
### パッケージインストール
``` sh
yum install -y zip
```

### aws cliのインストール
- aws cli
    - CLIでAWSを操作するための公式ライブラリ
    - セキュリティ認証情報を登録することで有効化
        - 実行したユーザに基づいて紐づけられる
        - 下記を統一
            - バックアップshellの実行権限を持つユーザ
            - 「aws configure」を実行して、認証情報を紐づけるユーザ
            - cronにバックアップshellを設定するユーザ

#### CentOS7
``` sh
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"

python get-pip.py

pip install awscli

aws configure
```


#### CentOS6
pythonは2.7以上必須

``` sh
yum install -y centos-release-scl-rh

yum install -y python27

scl enable python27 bash

curl -O https://bootstrap.pypa.io/get-pip.py

python get-pip.py

pip install awscli --upgrade

aws configure
```

# 実装
## 環境に応じて変更する個所
- 保存ディレクトリ
- s3ディレクトリ
- 保存上限個数
- バックアップ対象

## コード
``` sh
#!/bin/sh

# 対象名
SRC_NAME=cs
# 保存ディレクトリ
DIR_TMP=/home/centos/backup
# S3ディレクトリ
DIR_S3=s3://backup
# 保存上限個数
LIMIT=3

# 前回ファイル削除
rm -rf $DIR_TMP/$SRC_NAME/*

# 日時取得
TODAY=`date +%Y%m%d%H%M`

# ディレクトリ作成
mkdir -p $DIR_TMP/$SRC_NAME/$TODAY

# 情報取得
cp -r /var/www/html $DIR_TMP/$SRC_NAME/$TODAY
mysqldump -u mysql -r $DIR_TMP/$SRC_NAME/$TODAY/mysqldump.sql --single-transaction --default-character-set=binary -B table_name

# 圧縮
zip -r $DIR_TMP/$SRC_NAME/$TODAY.zip $DIR_TMP/$SRC_NAME/$TODAY

# 転送
aws s3 cp $DIR_TMP/$SRC_NAME/$TODAY.zip $DIR_S3/$SRC_NAME/

# 過程ファイル削除（念のため、zipは次回まで残す）
rm -rf $DIR_TMP/$SRC_NAME/$TODAY

# 期限切れファイル削除
COUNT=0
for l in `aws s3 ls $DIR_S3/$SRC_NAME/ | sort -nr`; do
    if echo $l | grep "zip"; then
        # 上限以上のファイル削除
        if [[ $COUNT -ge $LIMIT ]]; then
        aws s3 rm $DIR_S3/$SRC_NAME/$l
        fi

        # カウンタ更新
        COUNT=$(( COUNT + 1 ))
    fi

done
```

## cron設定
``` sh
crontab -e

    0 1 * * * sh /home/centos/backup.sh
```
kintoneにボタンを置いて任意のフィールドをクリップボードにコピーする

kintoneの詳細画面とかにボタンを置いて、押すと任意のフィールドをコピーする。

* `memo_markdown`この部分を任意のコピーしたいフィールドのフィールドコードに変更。
* 「スペース」フィールドの配置が必要。今回は`copy_button`というフィールドコードで配置。
* jQueryは読み込み必要。


```javascript:sample.js
(function($) {
  'use strict';
  let events = [
    'app.record.create.show',
    'app.record.edit.show',
    'app.record.detail.show'
  ]
  kintone.events.on(events, function(event){
    let el = kintone.app.record.getSpaceElement('copy_button');
    $('<input />', {
      'type': 'button',
      'name': 'c_button',
      'value': 'Copy',
      'class': 'create_button',
    }).on('click', function (resp) {
      let copyFrom = document.createElement("textarea");
      copyFrom.textContent = event.record.memo_markdown.value;
      let bodyElm = document.getElementsByTagName("body")[0];
      bodyElm.appendChild(copyFrom);
      copyFrom.select();
      document.execCommand('copy');
      alert("リリースノートをコピーしました。");
      bodyElm.removeChild(copyFrom);
    }).appendTo(el);
  });
})(jQuery);

```
[Swift]カウントダウンタイマー

初心者の方必見！！！
Swift5にてカウントダウンタイマーを作成します。

<img width="362" alt="スクリーンショット 2019-08-23 16.43.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486519/275115bb-6885-2a7d-4367-d5542596eb78.png">
このようなカウントダウンタイマーです。
意外とネット上のコードは使えないものが多いので、重宝すると思います。


このアプリを実行するには２つのファイルに書き出します。
・DataManager.swift (ファイルの作成が必要)
・ViewController.swift（最初からあります）




```DateManager.swift
import Foundation
import UIKit

class DateManager {
    
    private let formatter = DateFormatter()
    private let date = Date()
    private var dateStr: String?
    private let calendar = Calendar(identifier: .gregorian)
    
    init(){
        formatter.timeZone = TimeZone.ReferenceType.local
        formatter.dateFormat = "yyyy-MM-dd-HH-mm-ss"
        dateStr = ""
    }
    //現在時刻を返します"yyyy-MM-dd-HH-mm-ss"
    func getNowDate() -> String{
        dateStr = formatter.string(from: date)
        guard let now = dateStr else { return ""}
        return now
    }
    //設定したカウントダウンの秒数を返してくれます
    func getXmaxTimeInterval() -> Int {
        guard let xmas = calendar.date(from: DateComponents(year: 2019, month: 12, day: 25)) else { return 0}
        let spanFromWow = xmas.timeIntervalSinceNow
        return Int(floor(spanFromWow))
    }
    
}

```



```ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var snowView: UIView!
    @IBOutlet weak var countLabel: UILabel!
    
    let date = DateManager()
    var timer: Timer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)
        //カウントダウン
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.update), userInfo: nil, repeats: true)
        timer.fire()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)
        timer.invalidate()
        timer = nil
    }
    
    @objc func update(tm: Timer) {
        
        let count: Int = date.getXmaxTimeInterval()
        let count2: TimeInterval = TimeInterval(count)
        let formatter = DateComponentsFormatter()
        
        // 表示フォーマットを変更．.positionalや.fullで表示が変わります．
        formatter.unitsStyle = .brief
        // 使用する単位　.minuteのみにすると232,071minのように出力されます．
        formatter.allowedUnits = [.year, .month, .day, .hour, .minute, .second]
        // 作成したformatterでtimeintervalをstringに変換します．
        print(formatter.string(from: count2)!) // →5mths 10days 3hr 44min 28sec
        //時間をラベルに表示
        countLabel.text = formatter.string(from: count2)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
}

```

StoryBoardにてラベルと背景画像をOutlet接続したら完成します。

できたらコメントにグヘグヘ！お願いしますw
分からないことがありましたら、遠慮なくコメントくださいね。
Macでbundle installしたらjsonが入れられないって怒られた話

# 環境
macOS mojave(10.14.6)
同じ状況になった人が解決したら幸いです

# 状況
カバレッジを測定するためにプロジェクトチームで`simplecov`を入れた
`bundle install`すると俺だけ以下エラーがでた

```
An error occurred while installing json (2.2.0), and Bundler cannot continue.
Make sure that `gem install json -v '2.2.0' --source 'https://rubygems.org/'` succeeds before bundling.
```

# 解決方法
ターミナルで以下を実行
`xcode-select install`
`brew install gcc`
【AWS】 AWS障害をきっかけに学んだ、EC2インスタンスのステータスチェックとは？

# はじめに
2019/08/23 13時頃　AWSの東京リージョンで大規模な障害が発生しました。
※参照：https://news.yahoo.co.jp/pickup/6334251

そこで、EC2インスタンスのステータスチェックが失敗していたので、停止して起動しなおすなどの対応していたのですが、そもそもステータスチェックって何してるのってなって詳しく知らなかったので、調べました。
この障害で、調べようと思いました。

# 内容
## 概要
ステータスチェックの「1/2」とか「0/2」とかなんですかってなりました。純情な感情・・・でしか見たことありません自分。はい。

話を戻すと、EC2を通常稼働できるかを検査してくれています。
例えば、ハードウェア的な問題があるよとかソフトウェアやネットワーク的な問題があるよって、自動化されたチェックを実行して問題を識別してくれています。

そこで、このステータスチェックには2つチェックするものがあります。それが、
- StatusCheckFailed_System
- StatusCheckFailed_Instance

「1/2」とか「2/2」とかは、このステータスの数を表していて、どちらかが失敗すると、エクスクラメーション・マークを出して教えてくれます。

以下ステータスチェックの仕組みを軽く引用しています。

---

> ステータスチェックは 1 分ごとに実行され、それぞれ成功または失敗のステータスが返ります。すべてのチェックが成功すると、インスタンス全体のステータスが OK になります。

※参考：https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html


> CloudWatchの見方としては、
・「EC2インスタンス内部に問題がある」ときは、「StatusCheckFailed_Instance」の値が１となっている。
・「AWS側のEC2ホスティングのシステム的な問題がある」ときは、「StatusCheckFailed_System」の値が１となっている。

※参考：https://dev.classmethod.jp/cloud/aws/cloudwatch-metrix-memo-1/


---

じゃあ具体的に、これらは何をしているか見てみます。

※下の参考記事を参考にしました。とても分かりやすかったです。

## 内容
### ■ StatusCheckFailed_System

```
・StatusCheckFailed_Instance : 個々のインスタンスのソフトウェアとネットワークの設定を監視します。
```
※参考：https://dev.classmethod.jp/cloud/aws/cloudwatch-metrix-memo-1/

#### ＜具体的内容＞
物理ホストでの問題が発生した場合のステータス。
AWS側の問題が原因で、利用者側の問題ではない可能性があります。
※ただし、EC2インスタンスを利用者がシャットダウンした場合には発生するようです。

つまり

- AWS側でネットワーク障害とか電源回りでの障害が発生したことによる問題だよ。
- インスタンスが停止していることが問題だよ。

ってこと見たいです。

### ■ StatusCheckFailed_Instance

```
・StatusCheckFailed_System : インスタンスを使用するために必要な AWS システムを監視して、AWS システムが正常に実行されていることを確認します。
```
※参考：https://dev.classmethod.jp/cloud/aws/cloudwatch-metrix-memo-1/

#### ＜具体的内容＞

EC2インスタンスのシステム的な問題。
→　ネットワークの設定誤りやソフトウェアの設定誤り、メモリ不足だったり、ファイルシステムの欠損、カーネル問題等々です。
これは、利用者側の問題であり、AWS側の問題ではない可能性があります。

つまり

- Windowsだと、ipconfigとかでIPアドレスを開放するとこのアラート発生するみたいです。
※OSの再起動で、IPがDHCPサーバによって再度アサインされて復旧します。

> （この手の実験するときは十分に注意してください。スナップショットを取得してから実験するのが確実です。疑似障害はAWS 管理コンソールから再起動して復帰できる範囲が必要です。ネットワークの設定を変更して再起動でももとに戻らない場合はリモートデスクトップやcliからも修正できなくなり元に戻らない可能性があります。）

※参考：https://awsjp.com/AWS/hikaku/StatusCheckFailed_System-StatusCheckFailed_Instance-hikaku.html


# 結論

EC2インスタンスのステータスチェックは、通常動作するために、問題がないかをチェックしているよ。
種類が2つ（StatusCheckFailed_System・StatusCheckFailed_Instance）あって、それぞれ物理的問題で発生した問題かチェックしたり、ネットワークの設定ミスの問題化をチェックしてくれるものです。


# 参考
- https://dev.classmethod.jp/cloud/aws/cloudwatch-metrix-memo-1/
- https://blog.putise.com/aws%E3%81%AEec2%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%81%A71-2%E3%81%AE%E6%84%8F%E5%91%B3%E3%81%AF%EF%BC%9F%E3%83%93%E3%83%83%E3%82%AF%E3%83%AA%E3%83%9E/
- https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/monitoring-system-instance-status-check.html
- https://awsjp.com/AWS/hikaku/StatusCheckFailed_System-StatusCheckFailed_Instance-hikaku.html
開発中のrubyアプリのバージョンアップしようとしたらバージョン変わらなくて大変だった【2.5.5から2.6.3】

#バージョンをあげるキッカケ
GAEでポートフォリオをデプロイしようとしたら、rubyのバージョンが違うと怒られたのでアプリのrubyのバージョンを上げることにしました。（多分、GAEのバージョンを下げることも出来たんだろうけども勉強として開発中の物をバージョンあげることにしました。）

#1.現状の環境

ruby 2.5.5
Rails 5.2.3

#2.最新のバージョンをインストール

##2-1.自分のPCのバージョン確認
```terminal
$ rbenv versions
  system
* 2.5.5 (set by /Users/nns/Documents/GitHub/smoking/.ruby-version)
```

##2-2.rubyの最新バージョンの確認

```terminal
$ rbenv install --list
  ...
  2.6.0-preview1
  2.6.0-preview2
  2.6.0-preview3
  2.6.0-rc1
  2.6.0-rc2
  2.6.0
  2.6.1
  2.6.2
  2.6.3
  2.7.0-dev
  2.7.0-preview1
  jruby-1.5.6
  ...
```
今回はサーバーの環境に合わせて「2.6.3」に変更していこうと思います。
※最新のバージョンが表示されない人は<a href=https://qiita.com/Nash-BETA/items/ad514b79421f8460042b>こちら</a>

##2-3.rubyのインストール
```terminal
 $ rbenv install 2.6.3
ruby-build: using openssl from homebrew
Downloading ruby-2.6.3.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.bz2
Installing ruby-2.6.3...
```

コマンドを入力後インストールが始まるので数分放置

##2-4.バージョンの確認
```terminal
$ rbenv versions
  system
* 2.5.5 (set by /Users/nns/Documents/GitHub/smoking/.ruby-version)
  2.6.3
```

#3.最新のバージョンへ変更（めっちゃ大変だった）

##3-1.バージョンの変更
```terminal
$ rbenv global 2.6.3
```
上記を行いえば変わるはず。

```terminal
$ rbenv versions
  system
* 2.5.5 (set by /Users/nns/Documents/GitHub/smoking/.ruby-version)
  2.6.3
```

変わらない・・・

##3-2.バージョンの変更・続

Gemfileいじって**bundle update**ばどうにかなるんじゃね？
と思いGemfileのrubyのバージョンを変更

```ruby:Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'　#元の記述は　ruby '2.5.5'
```


```terminal
$ bundle update
Ignoring nokogiri-1.10.3 because its extensions are not built. Try: gem pristine nokogiri --version 1.10.3
Your Ruby version is 2.5.5, but your Gemfile specified 2.6.3

```

うん、エラッた。
Gemfile的には、2.5.5なのになんで2.6.3なんやねん。って感じなのかな？


##3-2.バージョンの変更・続々

どうやるのかなーと思った矢先にリポジトリを見ていると
<img width="301" alt="ruby-version" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/454305/e71d8498-b46d-62e8-658b-11f99719f424.png">

明らかに怪しい・・・中身を見てみると

```text:.ruby-version
2.5.5
```

なんかそれっぽかったので2.6.3に書き換えて

```text:.ruby-version
2.6.3
```

```terminal
$ rbenv versions
  system
  2.5.5 (set by /Users/nns/Documents/GitHub/smoking/.ruby-version)
* 2.6.3
```

無事完了っぽい。

改めてGemfileを書き換えて、**bundle update**の実行。

```ruby:Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.3'　#元の記述は　ruby '2.5.5'
```

```terminal
$ bundle update
```

問題なく動いたのでおそらくバージョンアップは完了。
Slack appについてのメモ

Slack Appを作っててこれどうやんだっけ？ってなったことのメモです

### AppDirectoryに出さないアプリを他のワークスペースにインストールさせたいとき

- Manage Distributionのページで、Activate Public Distributionを押す
- Manage DistributionのページでにあるSlack Buttonのリンクを貼り付ける
- [Slack Button \| Slack](https://api.slack.com/docs/slack-button)　で生成されるやつはサンプル用？なのでそのままは使えない

### Slackの左サイドにあるApp欄からのDMという形式にしたい時

- Add bot userでbotを追加する。スコープにbotを入れる（勝手に入る
- oauthするときにはidenity.basicあたりがはいっててuser_idはわかる（ホンマか？
- bot_access_tokenとuser_idを使ってプライベートチャンネルを開く
- bot_access_tokenとchannel_idでpostMessageする
iOS13からモーダルを閉じた時ViewWillAppear, ViewDidAppearが呼ばれない

# 環境
Xcode11 beta5
iPhoneXs iOS13

# 経緯

モーダルを閉じた時の`ViewWillAppear`で実行するテストがコケていた。
よくよく調べてみるとモーダルが閉じられた時に`ViewWillAppear`,`ViewDidAppear`が呼ばれていない...
iOS13からの[仕様変更](https://forums.developer.apple.com/thread/119675)によるものらしい
これ結構影響範囲大きい気がしますが...

## デフォルトのUIが変わっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47337/a40da4fc-bca2-0601-a2eb-2a7bc629b8bf.png)
なんてことだ、デフォルトでカード式になってますね
Xcode11でビルドすると遷移がデフォルトでカード式に変更される(Xcode11beta5時点)

# 対策
ひとまずフォーラムに書き込まれているやり方で対応してみる
StoryBoardのSegueの設定から`Presentation`を`FullScreen`にすることで
従来の画面いっぱい表示に戻せる
`FullScreen`にすることで`ViewWillAppear`,`ViewDidAppear`が無事コールされるようになりました🐬

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47337/1cfb4bc5-7a82-7740-823a-f5c635719920.png" width=300>
float解除にoverflow:hiddenを使うとまずい例

CSSで要素をfloatさせてレイアウトした時、後続要素のfloatを解除する方法として、[clearfix hack](https://csscreator.com/attributes/containedfloat.php)のほかに、float要素の親要素に`overflow: hidden`を指定することにより、floatで潰れてしまった高さを認識させる方法があります。この方法はclearfixに比べCSSへの記述が簡単なので初心者にはとっつきやすいですが、ページのデザインによっては使いどころに注意が必要です。

たとえばこの現象（下図）。これは、高さが異なる２つのdiv要素をそれぞれ`float: left`, `float: right`で配置したものです。floatしたdivのサイズと表示位置をブラウザ画面上で確認するため、CSSに`outline: 1px solid red;`を指定して要素の矩形領域を表示させたつもりが、ヘンテコな表示になってしまいました。
![float-outline_50p.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469745/ed1e387b-a505-c236-4ddb-e602b4b554ad.png)

```
<div class="container">
  <div class="left">Lorem ipsum dolor sit amet.</div>
  <div class="right">Lorem ipsum dolor sit amet.</div>
</div>
```

<details><summary>CSSの内容</summary><div>

```
.container {
  width: 700px;
  margin: 50px auto 0;
  overflow: hidden;
}
.left {
  float: left;
  width: 300px;
  height: 200px;
  margin-left: 20px;
  outline: 1px solid red;
}
.right {
  float: right;
  width: 300px;
  height: 100px;
  outline: 1px solid red;
}
```
</div></details>

なぜこんな表示の欠けが生じるのでしょう？ 輪郭線[outlineプロパティに関するMDNの解説](https://developer.mozilla.org/ja/docs/Web/CSS/outline#Borders_vs._outlines)を読んでやっと原因がわかりました。
> 輪郭線は以下の点で境界線とは異なります。
> 輪郭線は領域を占有せず、要素のコンテンツの外側に描かれます。

CSSの仕様でいうと該当箇所はこれか。[4.5. Offsetting the Outline: the outline-offset property](https://drafts.csswg.org/css-ui-3/#outline-offset)
> By default, the outline is drawn starting just outside the border edge. 

つまり、要素のborder含んだ領域の**外側に**輪郭線(outline)が描画されるため、親要素の`overflow: hidden`によって輪郭線が切り取られてしまったわけですね。上のスクリーンショットで、左側にfloatしたブロック要素については左辺のoutlineが欠けずに表示できていますが、実は`div.left`に`margin-left: 20px;`を設定していたからです。
ちなみに、上に述べたoutline-offsetプロパティを使って、`outline-offset: -1px;`を追加すれば、輪郭線を矩形の内側方向（borderの位置）に表示させることができます。

もっとありがちな例だと、`box-shadow`で影を付けたブロック要素を横並びにfloatで配置した時、右端のブロックだけ影がクリッピングされてしまうことがあります。この現象も、borderの外側に広がった影が、float解除のoverflowプロパティによって切り取られたのが原因です。

## float要素の表示欠けが生じるコード例
上に紹介したものに加え、`oveflow: hidden`によるfloat解除でfloat要素の「表示欠け」を起こす可能性のあるプロパティの使い方とそのサンプルコードを下記Penに書きました。
<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="result" data-user="kaz_hashimoto" data-slug-hash="gOYwJWN" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="[CSS basics] Clearing floats with overflow:hidden or clearfix">
  <span>See the Pen <a href="https://codepen.io/kaz_hashimoto/pen/gOYwJWN/">
  [CSS basics] Clearing floats with overflow:hidden or clearfix</a> by Kazuhiro Hashimoto (<a href="https://codepen.io/kaz_hashimoto">@kaz_hashimoto</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
このPenは、6種類のプロパティについて、float解除をそれぞれ「`overflow: hidden`で実施した場合」「clearfixで実施した場合」の計12個のサンプルを表示します。各サンプルの構成は以下のとおりです。

* 背景黒の長方形： 親要素div.container
* 白い枠線の長方形： float要素div.left, div.right
Hello ansible


## １．目的

Ansibleの触りを体験することが目的です。具体的には、EC2にAnsibleをインストールして、helloword的なことを実行して、初期動作確認を行います。


## ２．ansibleの嬉しいところ

- 冪等性（べきとうせい）による構成情報の担保
- Agent-less（Server側にSWは不要）
　 

その他Tips
・ Serverに対するアクセスはsshでアクセスする。
・ hostsファイルにアクセスするホストをグルーピングできる。
・ playbook（タスク書く設定ファイル）はyaml形式で設定を表現することができ表現が簡潔。
・ playbookからモジュール（よくある処理）を引用することができる。
・ RHEL純正のGUIツール（ansible tower）を用いることもできる（但し、有償）。
・冪等性（べきとうせい）は標準モジュールで作成したPlaybookのみOK


## ３．試したこと

1. 環境をインストール

以下コマンドを実行して、ansible本体をインストールします。

```
sudo yum -y install python-devel openssl-devel gcc git
sudo easy_install pip
sudo pip install ansible
```

ansible --versionを実行して、バージョンが表示されればインストール完了となります。

```
 ansible --version
ansible 2.9.4
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.16 (default, Dec 12 2019, 23:58:22) [GCC 7.3.1 20180712 (Red Hat 7.3.1-6)]
```




2. 以下（/etc/ansible/tasks配下）にtest.ymlを作成。
　

```
├── ansible.cfg
├── hosts
├── roles
└── tasks
    └── test1.yml
```

③test.ymlの中身

```
- hosts: localhost
  tasks:
  - name: touch text file
    shell: touch test.txt
```

④test.ymlの実行（local hostにtest.txtを作成）
```
sudo ansible-playbook test1.yml
```


⑤実行結果（text fileを作成できました）

```
├── ansible.cfg
├── hosts
├── roles
└── tasks
    ├── test1.yml
    └── test.txt
```

以上

## ４．Link
・ansibleとは
https://qiita.com/Brutus/items/1894629105d61f4854bc

・シェルスクリプトとの差分、他の構成管理ツールではなくAnsibleの理由
https://qiita.com/dhiki1234/items/e2d3a092dfb11361a49b

・Ciscoの拡張モジュール
https://gblogs.cisco.com/jp/2016/11/ansible-ios-related/

・GUI（Ansible Tower）について
https://docs.ansible.com/ansible-tower/

・冪等性が担保できる範囲について
https://dev.classmethod.jp/server-side/ansible/ansible_playbook_with_idempotence/

・よく使用する標準モジュールのまとめ
https://dev.classmethod.jp/server-side/ansible/ansible-my-reference/
AI(人工知能)がこれからどのように世界を変えていくのか？


中国検索エンジン最大手「百度Baidu」創業者であり、現会長兼CEO李彦宏（英語名：ロビン・リー）はTime Asiaの2019年１月29号の「The Innovator」表紙に登場しました。 中国のIT起業家がTime Asiaの表紙に登場したのは今回初めてです。作品の見出しには、「Baidu's Robin Li is Helping China Win the 21st Century」（Baiduのロビン・リーが中国21世紀の勝利を大きく支えている」と書かれています。 
![01-「百度Baidu」創業者李彦宏.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262932/b45fcc4a-e27f-4a2b-e614-6e84b87338c8.jpeg)

Baiduは中国でかなり物議を醸す大手企業の1つですが、なぜTime Asiaは、この会社にそこまで非常に高く評価しているのでしょうか？ これは、21世紀に世界の生産性に影響を与える主な要因であるAI（人工知能）から語ります。

11月にワシントンで開催されたAI（人工知能）およびグローバルセキュリティサミットで、Google Alphabetの会長であるエリック・シュミット氏は中国のAIについて「中国は2030年までに世界のAI産業を支配する役割になるだろう」と言った。 そして、ロシアのプーチン大統領も「AIを支配できる国は世界を支配できるのだろう」と話しました。**AIはすでに世界に大きな影響を与え、今後数年間で爆発なスピードで進化することに間違いありません。さらに第四回の産業革命を起こすことになるかもしれませんね。**

![02-人工知能.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262932/8b16c163-6217-958d-1eab-124394dc09f5.jpeg)

 

AIは現代社会において非常に重要な役割になってきたため、それに関する知識を完全に把握できなくても、それについて学び、理解する機会を人々に提供すべきだと思います。人工知能はかなり前から存在しており、もはや新しいものではありませんが、やはり人工知能は実際に何であろうかと思う人がたくさんいると思います。したがって、この記事では、AIとは何か、そしてAIがどのように世界を変えるかについて簡単に説明します。

李彦宏会長の言葉でいうと、「私たちが想像している未来は、人間が人間の言葉を使ってすべてのデバイスと対話できることです。人間と動物の違いは、人間が道具を使うことができることだ。過去10万年にわたって、人間は将来のために道具の使い方を習ってきました。しかし、AIの時代では道具が人間の言語と意図を理解する方法を学ぶ未来となると確信しています。」

道具は、人間の言語、人間の意図を理解する方法を学びます。かつて人間が道具や製品について学ぶことを必要とされました。これと同じに、道具は私たちについて学び始め、私たちの意図が何だろうかを理解し始めるプロセスはAI(人工知能)です。ですが、問題となっているのは、道具はいかにすれば、人間と同じくらい複雑なものをよりよく理解できるのかということです。

神様は、他のすべての動植物とは異なり、目、体の動き、声を通して感情や思考を表現する能力を持つ人間を創造しました。道具に書かれた文字を目で読んだり、手で道具を使ったりすることができます。もちろん、自分の目で人を見たり、それから、話し合ったり、そのひとのことを理解しようとしたりすることができます。これは人間なんです。ですが、道具にも手、耳や口などが埋め込めれば、人間と同じように、他の道具または人間を理解することができるのだろうか。

人間を理解することが可能ですが、道具に目、手、口が埋め込まれることはないでしょう。技術進化につれて、人間はカメラ技術、赤外線技術、音声技術などの技術を合わせて人間の目としての役割を務めています。それによって人々の動作や話し方をキャプチャするこことができます。これらを機械学習アルゴリズム、モデル、ビッグデータ、データマッピング、アルゴリズムと組み合わせると、顔認識、ジェスチャー認識、音声認識の技術が生まれました。


#**AIはどのような私たちの生活に影響を与えますか？**

道具はあなた自身よりも自分のことをよく理解していると、驚きまませんか。いくつかの例を見てみましょう。

1.エアコンは、あなたがいる場所の環境によって、空気の流れと温度を調整できるようになります。あなたよりも居心地のよい環境を一番早く把握できます。

2.AppleのSiriのように、基本的なニーズのほかに、答えがわからない時、または退屈になった時に、暇つぶしとして付き合ってくれる道具もあります。

3.クラウド上のデータをローカル共有するにはより早いスピードで実現でき、外側への情報漏れの心配がありません。 

#**今後AIが爆発なスピードで進化していくのはなぜですか？**
テクノロジーは進化していますが、最も重要なものは5Gネットワークです。4Gはすでに十分な速度ではないかと聞く人がいるかもしれません。確かにそうですが、5Gは4Gよりも100倍早く、Youtubeでビデオを視聴したり、ライブビデオを視聴したりするなど、あらゆる場面で使用できます。画像認識、ジェスチャー認識、顔認識、または音声認識の処理時間が大幅に短縮され、デバイス間のインタラクティブな接続が可能になります。5Gの登場は、AIの分野に基盤となる影響を与えると考えられます。

![03-人工知能2.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262932/aea47fdc-8de5-4c2b-5630-0e523bbcdfdd.jpeg)

将来、AIは大きな技術革新を引き起こし、人類の未来に多大な影響を与えることに間違いないでしょう。
railsでurlを変更する方法

自分が、忘れないに為に、これからqiitaに忘備録的な感じで、色々書いていこうと思います。

バージョンと使用
---
ruby 2.5.3
rails 5.2.3
AWS
まず最初の状態
---
railsで何かしらを作ると、デフォルトだと、

```ruby:routes.rb
Rails.application.routes.draw do
  resources :users
end
```
上記のようにすると、routesとして、

```ruby
   posts GET    /posts(.:format)
        　POST   /posts(.:format)
 new_post GET    /posts/new(.:format)
edit_post GET    /posts/:id/edit(.:format)
     post GET    /posts/:id(.:format)
   　　　　PATCH  /posts/:id(.:format)
          PUT    /posts/:id(.:format)
          DELETE /posts/:id(.:format)
```
が出てくると思います。
これの`:id`の部分を変更しようと思います。

変更の仕方
---

例えば、モデルを作成していたとして、そのモデルが**name**カラムを持っていたとします。
そして、「今は`/users/:id`だけど、`/users/:name`に変えたい」
という時です。

まず、

```ruby:routes.rb
Rails.application.routes.draw do
  resources :users, param: :name
end
```

次に、controllerの変更です。
`:id`を使うのは, show, edit, update, destroyがありますが、
使うものは一緒なので、show以外は省略します、すみません。

controllerの変更はこんな感じです。

```ruby:users_controller.rb
def
  @user = User.find_by(name: params[:name])
end
```

この時、**User.find**ではなく、**User.find_by**使用します。
findは**idのみ**にしか使えないからです。

そんなこんなで、変更していくと`users/:name`が使えるようになると思います。

オプション
---

ただ、このままだと、`users/:id`でも、`users/:name`でも入れてしまいます。
なので自分は少しモデルに変更を加えました。

```ruby:user.rb
def to_param
  return self.name
end
```

自分はこれでいけました。

参考資料
---

[Rails で投稿のURLをランダムな文字列にする](https://blog.takuchalle.dev/post/2018/11/22/create_random_post_id/)
.eslintignore の配置場所は気をつけた方がいい


[ESLint v8.25.0](https://eslint.org/blog/2022/10/eslint-v8.25.0-released/) 以降から `.eslintignore` は廃止されました。
今後はESLintの設定ファイルの `ignores` で指定することになります。
以下は ESLint v8.25.0 より古いバージョンの記事になります。

ESLintを使っていて割と細かい設定が必要なのでメモしておく.

.eslintignore と .gitignore は同じ様な役割だが扱い方が全く違います. この違いを分かってないと期待した動作にはなりません. そこで具体的な違いを整理しました.

### TL;DR
- `.eslintignore` はプロジェクトルートに配置する.
  - eslintrcで `"root": true`を指定して同じディレクトリに配置するといい.
- `.eslintignore` はサブディレクトリには配置しない
- Dotファイル(`.babelrc.js`等)もチェック対象にするなら `.eslintignore` に `!.*.js` を追記する

### 違い
ESLint(v6.1.0)で確認したところ以下の違いがありました.

Gitの `.gitignore` はとても柔軟で以下の様に優先度をつけています

- 複数のディレクトリに配置できる
- 配置したディレクトリの設定が優先度が高く評価される
- デフォルトの設定は `.gitignore_global` で管理する

一方、ESLintの `.eslintignore` 以下の様になっています.

- eslintを実行したカレントディレクトリの `.eslintignore` のみ使用.
  - 設定を上書きしたり親ディレクトリをさかのぼって設定を探索することはない.
- デフォルトではdotfiles(`.*`) は除外されている.
  - `.babelrc.js` とかは無視されので設定を追加する必要がある.

上記の様な違いがあるため自分の場合は２つの対応をすることにしました.

- プロジェクトルート(eslintrcで `"root": true`を指定して同じディレクトリ)に配置することでトラブル回避.
- JSで書かれた設定(dotfiles)周りもチェックしたいので `.eslintignore` に `!.*.js` を追記.

他にも一度はESLintドキュメントにある程度書かれています.
自分の場合は `.gitignore` みたいなものだろうとドキュメントを眺めただけだったので、気がつきませんでした 🙈

- [Configuring ESLint - ESLint - Pluggable JavaScript linter](https://eslint.org/docs/user-guide/configuring#eslintignore)
自分の記事がストックされると通知が来るようになったよ。

最近Qiitaを開くと自分の記事が<b>ストック</b>されると通知が来るようになりました。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272803/529e9206-9a5c-2a4b-634c-dce7ba58b2e3.png)

通知設定にも<b>ストック</b>を通知するオプションが追加されていますね。
![通知設定.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272803/89cfba12-c40a-a4ef-01d7-612dcd24e69a.png)


ところが、記事上からは<b>ストック数</b>は確認できないようですね。
記事の<b>ストック数</b>や<b>ストック者</b>を確認したい場合は、こちらの拡張機能がオススメです。
[Qiitaのストック数を確認できる拡張機能を作った話](https://qiita.com/tonio0720/items/fefcdd5b88cdf239a5a1)
[QiitaStockers](https://chrome.google.com/webstore/detail/qiitastockers/amohnnngjiamaillkgdnafemejhdopbf)
Macのキーボード不具合を修理なしで(一部)解決する方法

バタフライキーボードを採用している最近のMacbookでは、キーボードを押しても効かない、連打されてしまうなどの問題が多数報告されています。

参考： https://misc-log.com/macbookpro-butterfly-keybord/

私のMacbookではよりによってエンターキーがたまに勝手に連打されるようになってしまい、チャットの途中で打ち掛けのテキストが思いがけず投稿されるなど、この症状にかなり苦しめられました。
そこで、キーコンフィグを編集することによって、思わぬ連打をかなり精度よく防げるようになる方法を発見したのでここで共有します。

## 方法

Karabiner-Elementsの`Complex Modifications`を利用します。

`$HOME/.config/karabiner/assets/complex_modifications/`配下にJSONファイルを作成し、以下のJSONを貼り付けます。

```modification_example.json
{
  "title": "Mistaken enter double-tap to single tap",
  "rules": [
    {
      "description": "mistaken enter double-tap to single tap",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "return_or_enter",
            "modifiers": { "optional": [ "any" ] }
          },
          "to": [
          ],
          "to_delayed_action": {
            "to_if_invoked": [
              { "key_code": "return_or_enter" }
            ],
            "to_if_canceled": [
            ]
          }
        }
      ]
    }
  ]
}
```

続いて、Karabiner-Elementsの設定画面から`Complex Modifications`タブを開き、`➕Add rule`ボタンを押すと追加できるルール一覧が表示されますので、その中から`mistaken enter double-tap to single tap`を選択し、`➕Enable`ボタンを押します。

![スクリーンショット 2019-08-23 15.02.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76265/3d06ad88-f782-8aaa-7dea-fe53e9843a9d.png)

## 解説

Karabinerは、keypushのイベントが各プロセスに通知される前に所定のルールに従って起きるイベントを制御します。

今回の場合、

```.json
          "from": {
            "key_code": "return_or_enter",
            "modifiers": { "optional": [ "any" ] }
          },
          "to": [
          ],
```

上記の`"from"`で指定した`return_or_enter`(エンターキー)が押された場合、`"to"`で指定したイベントが本来発行されるのですが、ここが空欄なので、keyが押された直後はなんのアクションも起きないことになります。
続いて、`"to_delayed_action"`の評価が走ります。

```.json
          "to_delayed_action": {
            "to_if_invoked": [
              { "key_code": "return_or_enter" }
            ],
            "to_if_canceled": [
            ]
          }
```

`"to_if_invoked"`は、`"from"`で指定したキーが押されて以降一定時間追加のキー入力がない場合に実行されます。
`"to_if_canceled"`は、`"from"`で指定したキーが押されて以降一定時間以内に追加のキー入力があった場合に実行されます。

キーボードの不具合による連打はほぼ即座に起きますから、連打が起こった場合は`"to_if_canceled"`が実行され、最初のkeypressはなかったことになります。続いて、連打の2回目のkeypressが同様のルールで評価され、追加の入力がなかった場合はエンターキーの入力が有効になります。

## delayed_actionの実行時間のチューニング

`"to_delayed_action"`の評価が走るまでの時間が長すぎると、普通のユーザの入力によってもエンターキーが無効になってしまう恐れがあります。また、ちょっとだけ`"to_delayed_action"`が走るまでのタイムラグを感じるようになります。
Karabiner-Elementsはそのタイムインターバルをパラメータとして指定できるので、自分の好みの数字に設定しましょう
この設定単体でいえば、`to_delayed_action_delay_milliseconds`を15程度に設定するとさほど遅延を感じずに連打防止の効果も得られていい感じでした。


![スクリーンショット 2019-08-23 15.18.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76265/327cb168-316a-772a-b0ff-6ea5f3ece4ff.png)


## まとめ

キーコードを変えれば任意のキーの連打防止に使えると思います。
これが悩めるMacユーザの助けになれば幸いです。
piwheelsにバイナリがない時どうすれば良いか、あるいは、いかにpiwheelsが重要かという話

# pandasの最新版、0.25.0のバイナリが無かった

昨日、ラズパイで、ふと、pandasやってみようと思いたち、インストールを試みました。

ところが、最新版のバイナリを取得できず、ソースのダウンロード、ビルドを初めてしまう。しかも、時間がかかったあとに、エラーが出まくって失敗。ツールがないとか、古いとか、あーでもないこーでもない、と、何度も失敗、かなり膨大な時間をかけて、成功。正常なビルド自体も75分かかり、割と大きいパケージですね。

pip自体のオプションや新しいツールについても学んだので、無駄ではなかったものの、かなり、根性がいりました。ビルドに必要な依存関係は、実行時の依存関係と比較して、あまり明確になっていないようですね。まぁ、そりゃそうか。

困るなと思いつつ75分もかけて手元でビルド。しかも、何台も。バイナリでの移動がよくわからなかったのと、ビルド環境ごと更新しておかないと、あとでより一層、面倒になりそうだったので。あと、75分放置するだけなので。

# なんで、バイナリがないの？ あるやつはどこにあるのか

pythonのパッケージ／モジュールは[PyPi (Python Package Index)](https://pypi.org)にソースがあります。主要パッケージ、主要プラットホーム、主要Pythonバージョン用にはビルド済バイナリもあります。
で、ラズパイは「主要」じゃないのでバイナリが無い。

それならば、自分たちでラズパイ用バイナリをビルドして、自前のwheelも作って公開しちゃえ。が、piwheelsです。主要なパッケージについてバイナリがあります。

# piwheelsすごい！

普段は、ダウンロードもビルドもそんなに時間がかからないので、どこからソースが来るのか、バイナリが来るのか、気にも留めてなかった。

wheelの存在、piwheelsができた経緯について、詳しくなりました。piwheelsの作者、Ben Nuttallは以前から知っていましたし、piwheels誕生について[ニュース](https://www.raspberrypi.org/blog/piwheels/)も[ブログ](https://bennuttall.com/tag/piwheels/)も[twitter](https://twitter.com/ben_nuttall/status/1041621905407651840)も読んでいましたが、その時にはピンと来てなかった。

piwheelsすごい！

今回のように自前でビルドするときに75分は厳しい。しかも、ビルドツールが整備されていないと無理、死ぬ。というわけで、piwheelsさまさまです。

# なんで、piwheelsに無いのか？

で、なんでpiwheelsに無かったのと思ってpiwheels packagesのissueを確認したら、ビルドに失敗していたことがわかり、さらにビルド時には、当時最新のnumpy-1.17.0rc2を使っていたことがわかりました。
https://github.com/piwheels/packages/issues/46

手元でのビルド時にも古いバージョンではエラーが出て、numpy-1.17.0を入れたら成功したので、その点を伝えたらBenがすぐにリトライしてくれてビルド成功！

numpyのリリース候補版、正式リリース版の間にpandasがリリースされていたんですね。RC版はリリース版とほぼ変わらないはずですが、見せてもらったエラーログを眺めた分には濃厚。

そもそも、RC版を使ってビルドするのはどうなんだろう？？

# バイナリがなかったら、まずpiwheels packagesのissueを確認！

piwheelsに最新バイナリがないときは、issueを上げたら解決につながる場合もあることを学びました。大勢のラズパイユーザーも助かる。

ちなみに、Benはラズパイ財団コミュティマネージャーです。Raspberry JAMなどで関わりがあります。PiWheelsだけでなくGPIO Zeroも彼がリードしています。https://bennuttall.com Ben Nuttallさまさま。

opencv関係も自動ではうまくいかなくて彼ら自身が手動でやっているものもあるようです。

# おい！ pandas-0.25.1がでてるやん！

で、昨日の今日、pandas-0.25.1が出てました。piwheelsにも既に上がっていて、問題なく自動ビルドできた模様。良かった。
https://www.piwheels.org/project/pandas/

```
Successfully installed pandas-0.25.1
real	1m24.284s
user	0m35.791s
sys	0m2.729s

python3 REPLにて
>>> import pandas
>>> pandas.__version__
'0.25.1'
```

というか、思い立ったのが一日遅かったら、何も気が付かないまま2分でインストール成功していたはず。そして、今回のことはなかった。運命か。

ということでエントリーを書きました。

[piwheels](https://twitter.com/piwheels)に感謝しよう!
そろそろ2周年なので、[Ben](https://twitter.com/ben_nuttall)にも感謝を伝えよう！


## おまけ

今回、新しく知ったツール、pipdeptree。
pipでインストールしたパッケージのdependency tree、依存関係を教えてくれます。

```
sudo pip3 install pipdeptree

pipdeptree -p pandas

pandas==0.25.1
  - numpy [required: >=1.13.3, installed: 1.17.0]
  - python-dateutil [required: >=2.6.1, installed: 2.8.0]
    - six [required: >=1.5, installed: 1.12.0]
  - pytz [required: >=2017.2, installed: 2019.2]
```
Pull Reminders で #Github のレビューリクエストを #Slack DM で自分宛に通知する

Notify yourself of #Github review requests via #Slack DM with Pull Reminders


https://pullreminders.com

ここから進んでいくだけ。初期設定で、自分宛にSlack DMが送られるようになってるっぽい。

![image](https://user-images.githubusercontent.com/13635059/63565512-4259ca80-c5a4-11e9-90bf-c7ad26f6919f.png)

![image](https://user-images.githubusercontent.com/13635059/63565527-4ede2300-c5a4-11e9-8352-745416be2f87.png)
![image](https://user-images.githubusercontent.com/13635059/63565541-5ac9e500-c5a4-11e9-803d-10fcedb759e9.png)
![image](https://user-images.githubusercontent.com/13635059/63565545-5f8e9900-c5a4-11e9-96a3-267e7c099cc5.png)


![image](https://user-images.githubusercontent.com/13635059/63565550-65847a00-c5a4-11e9-9cf4-6511b8fc1fdf.png)



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2320








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Zoho CardDAV は実質使えない

(初出: 2019-03-03 "Zoho CardDAV is NOT usable yet" を改題)

Zoho Mail の Calendar (カレンダー) や Contacts (連絡先) も ownCloud と同期すると便利だと思い、[vdirsyncer](https://github.com/pimutils/vdirsyncer) での同期を試みた。カレンダーの方は難なく同期できるが、Contacts がどうもいけない。Zoho 公式の (微妙に説明が足りない感じの) 説明に沿って、しかし試行錯誤の挙句、なんとか同期する設定を見つけ出したのだが、最初の16件 (この数字に意味があるかどうかは不明) だけ同期した後 WebDAV の長い長い応答待ちに入り、そこから戻ると今度はエラーが多発する。控えめに言って使い物にならない。vdirsyncer (pimutils) の開発者周辺では [Zoho のサーバー側の問題だ](https://github.com/pimutils/vdirsyncer/issues/534) という見方で、実際に Zoho 自身も [自分たちのバグだと認めている](https://help.zoho.com/portal/community/topic/carddav-support) ようである。残念。

しかし考えてみれば Zoho Contacts は姓名順の表示もできないしふりがなも扱えないから、たとえ同期できたとしても使いやすいとは言えない。今までのように、ownCloud が吐き出す VCF を適当に 山田 太郎 ⇔ Taro YAMADA 式に変換して手動でインポートすることにしよう。それ用のスクリプトは準備してあるから問題ない。

なお、vdirsyncer 用の「Zoho Contacts でなんとか同期に成功する設定」とは次のようなものだ。カレンダーの同期に利用するローカル (ファイルシステム上の) データの確認に khal を利用しているため、ここでは path に khal 用のフォルダーを指定している。

```ini
[pair contacts]
a = "contacts_local"
b = "contacts_remote"
collections = [["contacts", "<local address book name>", "contacts"]]
#conflict_resolution = "b wins"

[storage contacts_local]
type = "filesystem"
path = "/home/<username>/.local/share/khal/contacts/"
fileext = ".vcf"

[storage contacts_remote]
type = "carddav"
url = "https://contacts.zoho.com/carddav/<zoho email id>/default/contacts/"
username = "<zoho email id>"
password = "<zoho app password>"
```
users/idをURLに入力時のActiveRecord::RecordNotFoundの対処法

##URLに直接useridを入力した際のエラー画面redirectする

ユーザーが未登録、削除したユーザーのidをURLに書き込むと
赤の**エラー画面**になり見栄えが悪くなる。

そこで
`@user = User.find(params[:id])`
と普段しているところを
**find_by**に置き換えてあげる
また、**before_action**を先頭におき、他の機能が開始する前にここで審査弾くようにする
ここは必要におうじてアクションを追加する必要あり

```ruby:users_controller.rb
before_action :correct_user, only: [:edit,:show]

~~
~~

private

def correct_user
  @user = User.find_by(id: params[:id])
  unless current_user?(@user)
    flash[:danger] = "他のユーザーデータは観覧できません。"
    redirect_to (root_url)
  end
end
```

これで他人のデータは観覧できず、かつホームまでredirectしてflashで警告もだせる。
CosmosDBについての調査

人に見せるようではなく、自分で調べたことのまとめ。


## cosmosDBとは

> Azure Cosmos DB は、Microsoft によってグローバルに配布されるマルチモデル データベース サービス

> Cosmos DB では、ボタンを 1 つクリックするだけで、世界中の Azure リージョンをいくつでもまたいでスループットとストレージをエラスティックかつ個別にスケーリングできます。 スループットとストレージをエラスティックにスケーリングし、SQL、MongoDB、Cassandra、Tables、Gremlin などの好みの API を使用して、数ミリ秒 (1 桁) の高速データ アクセスを利用できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68103/2c983bcc-b457-a2a0-18cc-a7df307677ad.png)

[Azure Cosmos DB の概要 | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/cosmos-db/introduction)

> Azure Cosmos DB は、待機時間の短縮、スループットのエラスティックなスケーラビリティ、データの一貫性を保つための明確に定義されたセマンティクス、および高可用性を確保するように設計された、グローバル分散データベース サービスです。
MacのMySQLクライアント

## bashの場合

`brew install mysql --client-only`
ということだったんですが。
`Error: invalid option: --client-only`
というエラーになってしまったので。

`brew install mysql-client`
になったということだったんですが、MySQLが出てこない……

メッセージに書いてありました。

`echo 'export PATH="/usr/local/opt/mysql-client/bin:$PATH"' >> ~/.bash_profile`

ということで、上記を実施して、

`source ~/.bash_profile`

をすると使えるようになります。

## zshになって

macOS Catalina(10.15)からデフォルトのシェルが `zsh` になって、勝手が変わりました。
システムからのメッセージも変わっています。

```
% brew install mysql-client

If you need to have mysql-client first in your PATH run:
  echo 'export PATH="/usr/local/opt/mysql-client/bin:$PATH"' >> ~/.zshrc

For compilers to find mysql-client you may need to set:
  export LDFLAGS="-L/usr/local/opt/mysql-client/lib"
  export CPPFLAGS="-I/usr/local/opt/mysql-client/include"
```

そんな訳で、
`echo 'export PATH="/usr/local/opt/mysql-client/bin:$PATH"' >> ~/.zshrc`
を実行して、
`source ~/.zshrc`
を実行。

ローカルDBに
`% mysql -uroot -p -h127.0.0.1`
で繋がりました✌
HTML/CSS　勉強メモ

・親要素と子要素の関係
　子要素は親要素の左上にできる
　
　ブロック要素の高さのデフォルトは子要素の合計になる。<a><h1>
　ブロック要素の横幅のデフォルトは親要素と同じになる。

・ブロック要素
　要素の前後に改行が入る、ブロック要素同し縦に並ぶ
　横幅、高さを指定する事ができる
　余白（margin,padding）を指定できる
　例（div,li）
・インライン要素
　要素の前後に改行が入らない、インライン要素同し横に並ぶ
　横幅、高さを指定できない
　余白margin 左右は指定できる　上下は無理
     padding　上下左右指定できるが他の要素を考慮しないため被る可能性がある

横並びにするには
・display：
  ブロック要素の時改行したく無い時
　インライン要素の時高さと幅を指定したい時

・float:
  左や右に寄せたりする事ができる。しかし親要素の高さを０にしてしまう。
　それを無くすためには　clear:both;を使う
  

position:relative;　親要素
相対位置への配置
position: absolute; はスライドしたら見えない　子要素
絶対位置への配置
position: fixed;を使えばスライドしても常にそこにある状態になる。
絶対位置への配置

margin: auto;
要素の外側の範囲　autoは中央になるように余白を作る
padding:
要素の内側の範囲

float: left; right;
プロパティは、指定された要素を左または右に寄せて配置する際に使用します。

clear: both;
floatを指定した要素から子要素が認識できなくなります。そのため親要素は高さを保持できなくなります。
回り込みを解除するプロパティ。指定方法はfloatを指定した要素の次の要素に指定します。floatが連続している場合は最後の要素に指定します。

font-weight: bold;
文字の太さ

line-height 行の高さを指定する
font-sizeの指定した数字との差が指定される

リセットCSS　
元々ブラウザにあるCSSの値を変更するもの
.無しで記入する
文字列をリストにぶっこむ

ある文字列がある。

```python:test1.py
mojiretsu = 'aiueo'
```

これをリストに入れたかった。
やりたかったのはこれ。

```python:test1.py
print(mojiretsu_list[0]) # aiueo
print(mojiretsu_list[1]) # インデックスエラー
```

ところが

```python:test1.py
mojiretsu = 'aiueo'
mojiretsu_list = list(mojiretsu)
print(mojiretsu_list[0]) # a
print(mojiretsu_list[1]) # i
```

1文字ずついれられてしまった。
もちろん

```python:test1.py
mojiretsu = 'aiueo'
mojiretsu_list = []
mojiretsu_list.append(mojiretsu)
```

とやればいいのは知ってる。
ただこの文字列、リスト化してある関数の引数として渡したかったので
どうしても1行で書きたかった。

色々試行錯誤したけど、答えは案外単純だった。
[]で囲むだけ

```python:test1.py
func([mojiretsu])
```
社内勉強会 機械学習入門（4.Pythonでプログラムを書いてみよう）

今日は、いきなりPythonで機械学習のプログラムを書く前に「簡単なプログラム」を書いてみたいと思います。
# 題材
BMIを計算するプログラムです。

* 体重（kg）と身長（cm）を入力してもらい、計算した結果（BMI）を出力します。
* 計算式内の身長は、単位がメートル（m）なので、注意です。<br/>
```BMI計算式： 体重(kg) ÷ 身長(m)の2乗```


# コードを書いてみよう
Python仮想環境を有効化し、「jupyter notebook」を起動しましょう。
``` 以下のコマンドを実行
$ cd C:\ml-intro
$ env\Scripts\activate.bat
$ jupyter notebook
```

まずは、体重と身長を入力してもらうためのコード
weight、height という変数にinput関数（あらかじめ用意された組み込み関数）の結果を代入していますね。
Pythonの場合、変数は、名前（変数名）を決めるだけで、変数の型については、特に決めません。

```python
weight = input('体重(kg)を入力：')
height = input('身長(cm)を入力：')
```

jupyter notebook上で、上記のコードを書いて実行してみると、体重の入力をちゃんと求められましたね。
![2019-08-23_13h03_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/686a6f57-1578-8993-c82d-6738ebaf333d.png)

次に入力してもらった体重と身長をもとにBMIを計算して出力する部分です。
実は、input関数によって得た入力は、文字列なので、weight、heightは、文字列型という扱いになっています。
文字例型のままですと、数値計算ができないので、型変換する必要があります。
（小数点数を扱うので、浮動小数点数型に型変換します。）

```python
weight = float(weight)        # 文字列型から浮動小数点数型に型変換
height = float(height) / 100  # 型変換＆単位をcmからmに変換 
bmi = weight / (height ** 2)  # BMI計算式
print(bmi)                    # 標準出力する組み込み関数
```

実行結果は、こんな感じです。（BMIの値がちゃんと出力されました。）

![2019-08-23_13h42_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/e2cf49c7-88fb-41f7-ec50-991dc1193a7c.png)


# プログラムを改良してみよう
更に「日本肥満学会の肥満度判定基準」に従い、"肥満度"も合わせて出力してみましょう。

| BMI | 肥満度 |
|:--|:--|
| 18.5未満 | 低体重（やせ） |
| 18.5以上、25未満 | 普通体重 |
| 25以上、30未満 | 肥満（1度） |
| 30以上、35未満 | 肥満（2度） |
| 35以上、40未満 | 肥満（3度） |
| 40以上 | 肥満（4度） |

BMIの値によって、肥満度の出力を変えたいので、ifおよびelif構文による条件分岐ですね。
上から順番に条件式を判定し、trueになったブロックを実行すると以降の条件式は判定されず、構文全体が終了する点がポイントですね。

```python
if bmi < 18.5:
    print('低体重（やせ）')
elif bmi < 25.0:
    print('普通体重')
elif bmi < 30.0:
    print('肥満（1度）')
elif bmi < 35.0:
    print('肥満（2度）')
elif bmi < 40.0:
    print('肥満（3度）')
else:
    print('肥満（4度）')
```

実行結果は、こんな感じです。（肥満度もちゃんと出力されました。）
![2019-08-23_14h06_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101846/38c81356-a4c8-0fd6-a182-12b57f9df655.png)


# まとめ

今日は、Pythonで簡単なプログラムを書いてみました。
次回もPythonに慣れるため、もう少しプログラムを書いてみようと思います。

次回は、「5.続Pythonでプログラムを書いてみよう」です。
[社内勉強会 機械学習入門（5.続Pythonでプログラムを書いてみよう）](https://qiita.com/masami310/items/1a9140d1dfb71041e5d2)
#Rails + #Rspec で ActiveModel バリデーションのキー・種類まで検証する書き方

#Rails + #Rspec how to verify ActiveModel validation key / type


こんな感じ

```rb
it { expect(some_model_instance.errors.details[:user]).to include({ error: :blank }) }
```


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2319








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
deleteアクションがshowアクションに飛んでしまう.....

# deleteアクションがshowアクションに飛んでしまう

既存のアプリケーションに対し削除機能を追加するべく、作業中のこと

いつも通り、削除用のリンクを作って、終わり〜

```
 <%= link_to "削除", agenda_path(agenda.id), method: :delete, data:{ confirm: "削除しますか？" }, class: "btn-sm btn-danger"%>
```

....

showアクションに遷移してしまう。。。

原因は、

nokogiriのバージョンの問題でした

nokgiriを1.10.4へアップデート

```
$bundle update nokogiri
````

Gemfile.lockの記述を訂正

```
capybara (3.3.1)
      addressable
      mini_mime (>= 0.1.3)
      nokogiri (>= 1.10.4) ⇦こいつらを書き換え（全部！
      rack (>= 1.6.0)
      rack-test (>= 0.6.3)
      xpath (~> 3.1)
    carrierwave (1.2.2)
```

以上の手順で解決しました！
Python bottleでWeb API サーバーを立てる時の基本的な書き方

# はじめに
PythonのWebフレームワークといえばDjangoやFlask等が有名だと思いますが、Pythonで手軽にサクッとAPIサーバーを立ててみたいという時には、bottleはかなり有効な選択肢になります。本記事では、PythonのWebフレームワークの一つであるbottleを用いてAPIサーバーを立てる時の基本的な書き方について説明します。

# 実行環境
macOS Mojave 10.14.6
Python 3.7.3
bottle 0.12.17

# インストール
Python の仮想環境まではできているとします。
bootle のインストールは普通に

```
pip install bottle
```

でできます。

# Hello world

```python
from bottle import get, run

@get("/hello")
def hello():
    return "Hello, world."

if __name__ == '__main__':
    run(host="localhost", port=8080)
```
これを実行し、ブラウザから http://localhost:8080/hello にアクセスすると画面上に Hello, world. の文字が表示されます。

# ルーティング
このソースコードでは、`@get` デコレータで `/hello` へのGETリクエストに対する処理を指定しています。その他のHTTPメソッドについては、`@post`、`@put`、`@delete`デコレータを用いることでそれぞれPOSTメソッド、PUTメソッド、DELETEメソッドに対する処理を指定することができます。

また、以下のように動的なルーティングを指定することもできます。

```python
@get("/hello/<name>")
def hello(name):
    return f"Hello, {name}."
```

この例だと、http://localhost/hello/takeshi にアクセスすると画面に Hello, takeshi. と表示されます。パスパラメータを関数の引数として受け取れるわけです。

# リクエストの情報を受け取る
`bottle.request` を用いると、リクエストに関する各種情報を扱えます。

```python
from bottle import get, request

@get("/hello")
def hello():
    limit = request.params.get("limit")
    body = request.json
    header = request.get_header("Content-Type")
```

`request.params` はクエリパラメータの一覧を返します。
返り値の型は `bottle.FormDict` で、`dict` 型とほとんど同じように使えます。
`dict` にしたければ `dict(requset.params)` とすることもできます。

`request.json` はリクエストヘッダに `Content-Type: application/json` が指定されているとき、リクエストボディを `dict` で返します。
`Content-Type` が `application/json` でないときは `None` が返ります。
`Content-Type` にかかわらず `request.body` でリクエストボディを取得することができますが、`request.json` は `dict` 型を返してくれて扱いやすいので、 リクエストボディは `json` で受け取るようにするのが良いと思います。

`request.get_header(name)` はリクエストヘッダを取得します。
`request.headers` ですべてのリクエストヘッダに一気にアクセスすることもできます。

# HTTPレスポンスを返す
ここまでの例では関数は文字列を返していましたが、APIサーバーでは `bottle.HTTPResponse` クラスのオブジェクトを返すほうが良いです。

```python
from bottle import get, HTTPResponse

@get("/hello")
def hello():
    header = {"Content-Type": "application/json"}
    body = {"message": "OK"}
    res = HTTPResponse(status=200, body=body, headers=header)
    return res
```

`HTTPResponse` オブジェクトはステータスコードとレスポンスボディとレスポンスヘッダを渡して生成します。
レスポンスボディとレスポンスヘッダは後でつけることもできます。
ステータスコードは省略するとデフォルトのステータスコードが付与され、多くの場合 `200` となるようです。

```python
res = HTTPResponse()
res.body = {"message": "OK"}
res.set_header("Content-Type", "application/json")
# 上記と同じ res ができる
```

# おまけ：Herokuにデプロイする時は
Herokuではポートを動的に用意するらしいので、ポートの設定は環境変数を使って行います。具体的には、`os` モジュールをインポートして `run` 関数を以下のように書き換えるだけです。

```python
run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))
```

# おわりに
以上、bottleを使ってAPIサーバーを立てる時のよく使われると思われる書き方を一通りまとめてみました。
また他に何かあれば追記します。

# 参考リンク
[Bottle: Python Web Framework（公式）](http://bottlepy.org/docs/dev/index.html#)
[BottleのRequest/Responseオブジェクトをマスター](http://qiita.com/tomotaka_ito/items/62fc4d58d1be7867a158)
[Bottleを使って書いたWebアプリをHerokuに置くときにrun()を書き換えるのはなんで？](https://qiita.com/sgigagaeru/items/d0bffd18d1644d292b3d)