OmniAICreator/Qiita-1.07M huggingface dataset:
RaspberryPi (3 Model B+) へのOpenCV(3.4.2)のインストール

（この記事は2018/8/17に作成しました）

RaspberryPiにOpenCVをインストールします。

以前に別の方法で
sudo apt autoremove libopencv3


* RaspberryPi3 Model B+ (OS: RASPBIAN, version: June 2018) 
* Python3
* OpenCV3.4.2

を想定しています。下の記事を全面的に参考にさせていただきました。
参考リンク：https://qiita.com/nanbuwks/items/422eb405ceef84826ab4

#1. microSDからメモリのスワップ
作業にあたり、スワップメモリ容量を変更しておきます。当該モデルのメモリは1GBありますが、インストール時にメモリ容量がなくなる可能性があるためです。
メモリ容量は、以下のコマンドで確認します。

```:スワップメモリ容量の確認
$ free -h
```

microSDのメモリを割り当てます。1GB程度あれば十分と思われます。32GBであれば、2GBでも問題ないでしょう。
容量の変更は、"/etc/dphys-swapfile" を編集することで可能です。nanoを用いて編集します。

```ssh:メモリスワップに関する設定の変更
$ sudo nano /etc/dphys-swapfile
```

実行すると、nanoで当該ファイルの編集ができます。単位はMBになっていますので、1024に書き換えます。

```conf:dphys-swapfile
CONF_SWAPSIZE=1024
```

書き換え後、control + Xで終了、その後Yで編集内容を保存、Enterで離脱します。
設定が完了したら、スワップメモリの変更を実行します。
設定の反映のために、stop→startとコマンドを実行します。

```:設定の反映
$ sudo systemctl stop dphys-swapfile
$ sudo systemctl start dphys-swapfile
```

変更ができたか、もう一度容量を確認します。

```:スワップメモリ容量の確認
$ free -h
```

#2. インストール

OpenCVをインストールする前に、必要となるパッケージをインストールしておきます。
参考リンク先の内容をそのまま踏襲して、以下のように入力すれば良さそうです（すでにインストール済みのパッケージはスキップされます）。

```:必要となるパッケージのインストール
$ sudo apt-get install build-essential git cmake pkg-config libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libgtk2.0-dev libatlas-base-dev gfortran
```

```:Python3、pipのインストール
$ sudo apt-get install python3-dev python3-pip
```

# 3. OpenCVおよびOpenCV_contribをダウンロード

OpenCVに加え、基本的なパッケージが含まれるOpenCV_contribも同時にインストールします。
下記の通りにダウンロードします。参考リンク先では3.2.0となっているところは、最新バージョンの数字である3.4.2に変更します。

```:OpenCVおよびOpenCV_contribをダウンロード
$ cd ~
$ git clone https://github.com/Itseez/opencv.git
$ cd opencv
$ git checkout 3.4.2
$ cd ..
$ git clone https://github.com/Itseez/opencv_contrib.git
$ cd opencv_contrib/
$ git checkout 3.4.2
$ cd ..
```

numpyをインストールします。pipがインストール済みですので、pipを使用します。
使用するコマンドはpipではなく、pip3ですので注意してください。

```:numpyをダウンロード
$ sudo pip3 install numpy
```

それでは、ダウンロードしたOpenCVをインストールします。cmake以下に多くの変数がありますが、 "\" を挟めば改行することができます。その場合にも、行頭の "-D" は毎回指定してください。最後の".."まで記述してください。

```:ビルド
$ cd opencv
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
>     -D CMAKE_INSTALL_PREFIX=/usr/local \
>     -D INSTALL_PYTHON_EXAMPLES=ON \
>     -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
>     -D BUILD_EXAMPLES=ON ..
$ make -j 4
```
"make -j 4 "はCPUコアを4つ使ってビルドするという意味です。
ビルドには2時間以上かかりますので、RaspberryPiには手を触れないで待ちます。

最後にインストールします。

```:インストール
$ sudo make install
$ sudo ldconfig
```

インストールが終了したら、インストールができているか確認します。

```:インストール確認
$ Python3
>>>import cv2
>>>cv2.__version__
```

最新バージョン "3.4.2" が表示されていれば成功です。

（おわり）
マクドナルド店舗を地図上に表示

### 動機

qiitaへの投稿ってどんな感じか、よくある例で試してみる。

### 手順

1. マクドナルド公式サイトのお店・サービスのお店を探すのページの店舗検索にアクセスし、chrome のデベロッパーツールを使って、店舗名と位置情報を含んだ jsonデータを取得。
2. 漢字コードを変換して改行コードを挿入。(漢字コードはUTF-8、改行コードはviで調整)
3. Python で json を csv に変換。
4. Google Drive の Fusion Table で csvファイルをインポートし、緯度経度の列の属性を location に変更。
5. add map でマッピングする地図を追加し、location を指定してマッピング完了！

### 参考にした情報
- 日本一マクドナルドから遠い場所  
https://qiita.com/j_catfish/items/0d36a21b4744aa3e4870
- Pythonにおけるデータ入出力（CSV、JSON）  
https://qiita.com/Amtkxa/items/1bc945bf434ae910a85f
- GoogleマップにFusion Tablesを使ってマーカーを7万個描画する  
https://maps.multisoup.co.jp/blog/2419/
[Ruby][初心者] クラスメソッドを定義する

## クラスメソッドを定義

**クラスメソッドを定義するには二つの方法がある**
1、メソッドごとにクラスメソッドのする場合　
→ メソッド名の頭にselfをつけるとクラスメソッドになる

2、複数のメソッドをまとめてクラスメソッドにする場合
→　class << self  .... endで囲む

```
class Foo
  def self.first_method
   puts 'first'
  end

  class << self
    def second_method
      puts 'second'
    end

    def third_method
      puts 'third'
    end
  end
end

```

呼び出す時はクラス名.メソッド名の形で呼び出す

```
Foo.first_method
Foo.second_method
Foo.third_method
```
Railsのmigrationでbigintを使う

Rails5ではデフォルトで作成されるidがbigintになっているため、参照元テーブルのカラムをintegerで作成してしまうとforeign keyが作成できない。そのため、テーブルのカラムをbigintで作成する必要がある。

## 新規作成
```ruby
def change
  create_table :articles do |t|
    t.bigint :author_id
  end
end
```
## 追加
```ruby
def change
  add_column :articles, :author_id, :bigint
end
```

## ちなみに、、、

```ruby
def change
  create_tables :articles do |t|
    t.references :author
  end
end
```
としてもauthor_idがbigintで作成される。
Let's Encryptのワイルドカード証明書の取得と自動更新について(MyDNS)(2018/08現在)

Let's Encryptのワイルドーカード証明書ってナイスですよね。
5月にとったワイルドカード証明書の更新がミスっていたので設定し直しました。
情報が色々あって混乱したのでまとめます。

ワイルドカードの更新にはDNSのTXTレコード編集が必要です。
私はMyDNS使っているのでサービス謹製のツールを使います。
他のDNS使っている人はそれぞれスクリプト作るとか、作ってあるのを探すとかすれば良いと思います。

MyDNSのツール:
https://github.com/disco-v8/DirectEdit/

## なにはともあれcertbotのインストール

なんかgithubからcloneしてある人もいると思いますがまぁ、パッケージ管理のモノを使うのが楽だと思います。

```bash
# Ubuntu
sudo apt install certbot
# AmazonLinux2
sudo yum install certbot
```

## 既存の証明書を消す

既存であるやつはめんどくさいので消しましょうか。

```bash
sudo su
cd /etc/letsencrypt
rm -frv ./*
```

## MyDNSのツールを適当な所に落とす

私は`/var/www/letsencrypt`に`git clone`しました。

```bash
sudo su
mkdir -p /var/www/letsencrypt
cd /var/www/letsencrypt
git clone https://github.com/disco-v8/DirectEdit.git
```

## 証明書を取得する

普通の証明書とワイルドカード証明書を一気にとります。
ドメインとメールアドレスだけ変えてコマンド流してください。
`lovesaemi.daemon.asia`と`*.lovesaemi.daemon.asia`と`あなたのメールアドレス`のところね。

```bash
sudo su
certbot certonly --manual \
--preferred-challenges=dns \
--manual-auth-hook /var/www/letsencrypt/DirectEdit/txtregist.php \
--manual-cleanup-hook /var/www/letsencrypt/DirectEdit/txtdelete.php \
-d lovesaemi.daemon.asia -d *.lovesaemi.daemon.asia \
--server https://acme-v02.api.letsencrypt.org/directory \
--agree-tos -m あなたのメールアドレス \
--manual-public-ip-logging-ok
```

取れました。

## WEBサーバー設定して確認

ここはApacheとかNginxとかH2Oとかで作業変わると思うので割愛します。
普通の証明書もワイルドカードの証明書も一つになるので楽になりましたね。

## 自動更新の確認

確認はしとかないといけませんね
下記コマンド流してエラーが出ないことを確認します

```bash
# Apacheの場合
certbot renew --force-renew --dry-run --webroot-path /var/www/html/ --post-hook "systemctl reload httpd"
# H2Oの場合
certbot renew --force-renew --dry-run --webroot-path /var/www/html/ --post-hook "systemctl reload h2o"
```

うまくいけばエラーも表示されず問題ないことが確認できると思います。

## cron設定

実はまだ実際に更新するところは確認できてないんですけど。。
まぁ、こんな感じかな、と思います。

cronは以下みたいになります。
Ubuntuの場合です。AmazonLinuxとかだとcertbotとかのパスが違うと思うので`which`しましょ。
実際はWEBサーバーの`reload`とか`restart`とかしなくてもいけるっぽいことを書いているサイトがありましたが、どうなんでしょう？この辺はおいおい確かめていけば良いですかね。

```bash
# Ubuntu
  0   0  */5 *   *     /usr/bin/certbot renew --webroot-path /var/www/html/ --post-hook "/bin/systemctl reload h2o" >> /var/www/letsencrypt/update.log 2>&1
# とか
# AmazonLinux2
  0   0 */10 * *       /bin/certbot renew renew--webroot-path /var/www/html/ --post-hook "/bin/systemctl reload httpd" /dev/null 2>&1
```

## その他

ロードバランサー配下のWEBサーバーに個別に証明書とるときの特有のコマンドあるらしいですが割愛します。ロードバランサーに証明書つければ良いのではないかな、個人的には思いますが。

## 以上です

実際はまだ更新できていないのでわからんのですけど、多分うまいこと行くと思います。

## 追記(2019/01/29)

自動更新OKでございます。ノーメンテで運用中。
mkcertを使ってローカル環境でもDockerでも楽々SSL

## 概要
mkcertをTwitterで見てローカル環境でもDockerでも楽々にSSLができるとのことで試して見た。

## 環境
Docker for Mac

## ディレクトリ構成

ssl-test/
├── ssl-conf/
│　　├── httpd/
│　　│ 　　└── ssl.conf
│　　└── secret-keys/ 
│　　　　├── localhost+1.pem
│      　　　　└── localhost+1-key.pem
├── index.php
├── Dockerfile
└── docker-compose.yml

## docker-compose.ymlの記述
```docker-compose.yml
version: '3'
services: 
  ssl:
    build: ./
    ports:
      - 80:80
      - 443:443
    privileged: true
    volumes: 
      - ./:/var/www/html
    container_name: 'ssl'
```

## Dockerfileの記述
```Dockerfile
FROM centos:7.5.1804

RUN yum -y update

# 外部リポジトリ（EPEL, Remi）を追加
RUN yum -y install epel-release
RUN yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm

# apache その他 phpパッケージを導入
RUN yum -y install httpd
RUN yum -y install --enablerepo=remi,remi-php72 php php-cli php-common php-devel php-fpm php-gd php-mbstring php-mysqlnd php-pdo php-pear php-pecl-apcu php-soap php-xml php-xmlrpc 

RUN yum -y install mod_ssl openssl

CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

WORKDIR /var/www/html
```

## index.phpの記述
```php
<?php phpinfo(); ?>
// 記述は何でも良い
```

## Dockerfileのbuildおよびdocker-composeの立ち上げ
```shell
docker-compose build
docker-compose up -d
```

## ssl.confの作成
```shell
docker-compose exec ssl bash
cat /etc/httpd/conf.d/ssl.conf > /var/www/html/ssl.conf
```
作成した`ssl.conf`を`ssl-conf/httpd`ディレクトリに配置する。

## mkcertのインストール

コンテナの外に出て(`exit`外に出る)

```shell

brew install mkcert
mkcert -install
mkcert localhost 127.0.0.1

```
を実行する。

作成された`localhost+1.pem` `localhost+1-key.pem` を　`ssl-conf/secret-keys`に配置する。

## ssl.confの編集

```ssl.conf
- SSLCertificateFile /etc/pki/tls/certs/localhost.crt
+ SSLCertificateFile /var/www/html/ssl-conf/secret-keys/localhost+1.pem

- SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
+ SSLCertificateKeyFile /var/www/html/ssl-conf/secret-keys/localhost+1-key.pem
```

## dokcer-compse.ymlの編集

```docker-comopse.yml
version: '3'
services: 
  ssl:
    build: ./
    ports:
      - 80:80
      - 443:443
    privileged: true
    volumes: 
      - ./:/var/www/html
      - ./ssl-conf/httpd/ssl.conf:/etc/httpd/conf.d/ssl.conf
    container_name: 'ssl'
```

再度`docker-compose up -d`でコンテナを立ち上げ[locahlost](https://localhost/)に接続する。

<img width="246" alt="スクリーンショット 2018-08-18 12.22.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/133718/a48f5f1d-50d0-2725-5c96-ecf2173973fc.png">

## 参考
[mkcert](https://github.com/FiloSottile/mkcert)

## 更新
[Nginx版](https://qiita.com/ProjectEuropa/items/bde085cbeff7b7e69295)
【第３回】超初心者が書くSAPについてのメモ　〜ABAP(基本文法)〜

# **ABAPとは**
ABAP（アバップ）とはSAPシステムの開発や制作で使われるプログラミング言語のことです。
SAPに特化している言語のため、JavaやC言語のような人気の言語と比較するとあまり知られていない言語かもしれません。
しかしそんなABAPもJavaと一緒でオブジェクト指向型となっております。
また、プログラミング初心者（趣味の範囲でJavaは触ったことがあります）の私でも取っつきやすい言語だなと印象を受けました。

# **ABAPの基本**
ABAPの書式ルールを以下に記述します。

- 命令文は半角ローマ字（リテラルの中は日本語可能）
- 命令はキーワードで始まりピリオドで終わる
- 命令中のここの単語は半角スペースで区切る
- リテラル以外の文字は、大文字小文字を同一視する
- 同じキーワードの命令が続く場合チェーン命令を使うことで一文で記述可能
- 「IF~ENDIF」[CASE~ENDCASE]のように複数の命令が一連となる場合はキーワード毎に最後にピリオドを付ける
- 文の途中からコメントを記述したい場合は”（ダブルコーテーション）を記述する
- 最初からコメントを記述したい場合は＊を付ける

上記のルールを守ればある程度自由にプログラムを書くことができます。
また、ABAPは国語でいう「起承転結」のようにプログラム（イベント）の流れがある程度決まっています。
以下、プログラムの流れを上記の書式を交えて記述します。

1.データ宣言・定数宣言

```abap:ABAP
* データ宣言
DATA : 
    '変数名'　TYPE '型名',
    '変数名'　TYPE '型名'.

* 定数宣言
CONSTANTS:
   '変数名'　TYPE '型名' VALUE {値}.

```
※チェーン命令を使用しています。
※わかりやすいように記述しているためコピペだと構文エラーが発生します。

2.INITIALIZATION



```abap:ABAP

*入力画面表示前の処理（タイトル設定・初期値設定など）
p_langu = sy - langu.

```

3.AT SELECTION-SCREEN


入力画面入力直後の処理（入力値が正常かをチェック）

4.START-OF-SELECTION

主処理

5.END-OF-SELECTION

処理結果の表示など

参考HP
[SAP Keyword Documentation](https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abenabap.htm)

# **リンク集**

[ABAP Wikipedia](https://ja.wikipedia.org/wiki/ABAP)
バージョン管理の一連の流れ

```
$ cd rabbits
```
 
まず、このようにして、gitの支配下にいれたいフォルダ（今回は*rabbits*）にコマンドラインで移動させる。
　
　

```
$ git init

```
次に、このコマンドでリポジトリ（ワークツリー,インデックス,ローカルリポジトリ）の作成をおこなう。
　
　
gitでバージョン管理されているかどうかは、Cloud９では*(master)*という字がコマンドライン上に出ていればオッケー。また、フォルダ*rabbits*に*.git*フォルダがあるのかも確認するといいでしょう。
　
　
 
 
 ___
さて、フォルダrabbitsになんらかのファイル（今回は*leveret.txt*）を作成し、そこに変更を加えたことにしよう。

　
次にやることは

```
$ git add leveret.txt
```
でして、これによって変更した*leveret.txt*をワークツリーからインデックスへと**ステージする**。
　
　
　
いよいよ、コミットする（バージョン作成）ときがきましたよおおおお！！！

```
$ git commit 
```
で、さきほどインデックスへとステージさせたファイルをローカルリポジトリへとコミットさせる。

このとき、コミットメッセージが求められる。変更内容を手短に書き込み、nanoを終えることでローカルリポジトリへとコミットさせる。


　
　
あとは、このページに引いた横線より下のことを繰り返す。
　
　
　
　
　
　
　
てなことで！！
SQLZOO 「SELECT from Nobel Tutorial」 回答集

###＜2020/08/15 追記＞
現在、SQLの学習をSQLZOOで開始するのはあまりお勧めできません。
別のサービスの活用をご検討ください。

---


SQLZOO [「SELECT from Nobel Tutorial」](http://sqlzoo.net/wiki/SELECT_from_Nobel_Tutorial) の回答集を作成しました。
前回の[「basics」「SELECT from WORLD Tutorial」](https://qiita.com/TakahiroNAMBU/items/9147a574126f1caee047)の続編です。

---

##SELECT from Nobel Tutorial

1 . Winners from 1950

```
SELECT yr, subject, winner
  FROM nobel
 WHERE yr = 1950
```
>年を書き換えるだけ。

2 . 1962 Literature

```
SELECT winner
  FROM nobel
 WHERE yr = 1962
   AND subject = 'Literature'
```
>コピペスキルのトレーニングですね。

3 . Albert Einstein

```
SELECT yr, subject
FROM nobel
WHERE winner = 'Albert Einstein'
```
>yearを「yr」にするなら他のも省略してほしい...

4 . Recent Peace Prizes

```
SELECT winner
FROM nobel
WHERE subject = 'Peace' and yr >= 2000
```

5 . Literature in the 1980's

```
SELECT *
FROM nobel
WHERE subject = 'Literature'
  AND yr BETWEEN 1980 and 1989
```
>地味に初登場の「＊」は全カラムという意味です。

6 . Only Presidents

```
SELECT * 
FROM nobel
WHERE winner IN ('Theodore Roosevelt', 'Woodrow Wilson', 'Jimmy Carter', 'Barack Obama')
```
>

7 . John

```
SELECT winner
FROM nobel
WHERE winner LIKE 'John%'
```
>ジョン汁...（特に意味はないです）

8 . Chemistry and Physics from different years

```
SELECT * 
FROM nobel
WHERE (subject = 'Physics' and yr = 1980)
  OR (subject = 'Chemistry' and yr = 1984)
```
>算数的なカッコの使い方ですね。

9 . Exclude Chemists and Medics

```
SELECT * 
FROM nobel
WHERE yr = 1980
  AND subject NOT IN ('Chemistry', 'Medicine')
```
>NOT INの（）内でORを使わないように注意です。

10 . Early Medicine, Late Literature

```
SELECT * 
FROM nobel
WHERE (yr < 1910 and subject = 'Medicine')
  OR (yr >= 2004 and subject = 'Literature')
```
>ORとANDの使い分け。

11 . Umlaut

```
SELECT *
FROM nobel
WHERE winner = 'PETER GRÜNBERG'
```
>ビビらせてくる割にコピペですんなりいけるんですが、[ウムラウト文字を手打ちしたければこちらを参照](https://en.wikipedia.org/wiki/Ü#Keyboarding)

12 . Apostrophe

```
SELECT *
FROM nobel
WHERE winner = 'EUGENE O''NEILL'
```
>文字列内の「'」（シングルクオーテーション）は２個続けて書けばいいよ、ということ。

13 . Knights of the realm

```
SELECT winner, yr, subject
FROM nobel
WHERE winner LIKE 'Sir%'
  ORDER BY yr DESC, winner
```
>年だけ新しい順なので、DESCを用いる。@secondtac さん、 @soemono さん、ご指摘ありがとうございました。

14 . Chemistry and Physics last

```
SELECT winner, subject
  FROM nobel
 WHERE yr=1984
 ORDER BY subject IN ('Physics','Chemistry'), subject, winner
```
>突然ハイレベルなんですが、
要は「INに含まれるものに1を、それ以外には0を付与される」ことを利用し、それ順に並べるということをしています。

---
###続きはこちら
https://qiita.com/TakahiroNAMBU/items/8fcfe1aa8977bfcd201c
GCP AutoML Natural Languageのベンチマーク

# GCP AutoML Natural Languageのベンチマーク

## TL;DR

デモデータを利用して`AutoML Natural Language`と自作モデルの性能を比較してみました。
もう全部`AutoML Natural Language`でいいんじゃないかなぁ・・・。

## 背景

GCPUBイベントに参加したところ、AutoMLのβ公開が始まっていることを知ったので、自然言語処理用である`AutoML Natural Language`の性能を確認してみようと考えました。

`AutoML Vision`はShuhei Fujiwaraさんの[こちらの記事](https://cloudplatform-jp.googleblog.com/2018/03/automl-vision-in-action-from-ramen-to-branded-goods.html)をどうぞ。

## 対象データ

`AutoML Natural Language`の[公式ドキュメント](https://cloud.google.com/natural-language/automl/docs/quickstart?hl=ja)に掲載されている[デモデータ](https://cloud.google.com/natural-language/automl/docs/sample/happiness.csv?hl=ja)を利用しました。

## 自作モデル

特徴量となる入力文をWord2Vecを利用してToken Embeddingとして入力、GRUで学習するという内容になっています。
形態素解析せずに、kerasの`text_to_word_sequence`を利用しているので、入力に適さない品詞もそのままです。
また、フレームワークとしてkerasを利用しています。

詳細は[Jupyter Notebook](https://github.com/lhideki/automl-test/blob/master/train.ipynb)を参照してください。

## 性能の比較

### AutoML Natural Language

![](https://www.inoue-kobo.com/ai_ml/automl-benchmark/images/image1.png)

![](https://www.inoue-kobo.com/ai_ml/automl-benchmark/images/image2.png)

### 自作モデル

```
                  precision    recall  f1-score   support

         bonding       0.72      0.91      0.80       506
         leisure       0.74      0.56      0.64       298
       affection       0.92      0.90      0.91      1277
enjoy_the_moment       0.57      0.55      0.56       408
     achievement       0.84      0.85      0.85      1187
          nature       0.91      0.53      0.67        73
        exercise       0.73      0.84      0.78        61

     avg / total       0.82      0.81      0.81      3810
```

## 処理時間

### AutoML Natural Language

約4時間。

### 自作モデル

約30分。
後述のJupyter Notebookのアウトプットでは15分になっていますが、一度途中から学習を再開しているため、合計で30分程度になっています。

## コスト

### AutoML Natural Language

```
219.05 Minute	¥1,215.51
```

単価については[公式ドキュメント](https://cloud.google.com/natural-language/automl/pricing?hl=ja)を参照してください。

### 自作モデル

GPUとしてGTX 1060(6GB)を搭載したデスクトップパソコンで実行しました。
このため、電気代だけです。

## その他

とっても凄い`AutoML Natural Language`ですが、日本語はサポートされていないそうです。
実際に、ラベルに日本語を使うと正しく解釈されません。
ただし、特徴量としては日本語も入力ができたので、ラベルをコード化するなどで日本語を使ってみることはできると思われます。

その場合の性能は確認していないので、他の人の検証を期待します。

## 関連情報

* [Google Cloud AutoML Natural Language](https://cloud.google.com/natural-language/automl/docs/?hl=ja)
* [ラーメン二郎とブランド品で AutoML Vision の認識性能を試す](https://cloudplatform-jp.googleblog.com/2018/03/automl-vision-in-action-from-ramen-to-branded-goods.html)
スクレイピングの学習 Python3系 その2

# 前回の内容
[スクレイピングの学習 Python3系 その1](https://qiita.com/mizssy07/items/c84e3c3853bc818ee042)

# 改善点
CSVでダウンロード

# 手順
- 前回からと同じく環境はGoogle Colaboratory(ローカルに環境を整えなくても試せるから)
- ランタイムのタイプはPython3系(そっちのが良さそうだったので)
- `from google.colab import files`でファイルを扱えるようにする
- 作成した表をCSVのファイルにして、ダウンロードする

# 追加したコード

```python:
from google.colab import files

# CSVに出力
filename = "topics.csv" # ファイル名の指定
df.to_csv(filename, encoding = 'utf-8') #csvへの変換、encoding指定(おまじない)
files.download(filename) # ダウンロード
```

# 全体のコード

```python:
# coding: UTF-8
import pandas as pd
from bs4 import BeautifulSoup
import requests
from google.colab import files

# アクセスするURL = ニュートピ
url = "https://newstopics.jp/"

# htmlを取得、BeautifulSoupで扱う
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser') # BeautifulSoupの初期化

# aタグの中から、class=titleの含まれたものを取得
tags = soup.find_all("a", {"class": "title"})
# データフレームを作成。列名 name=記事名, url=url
columns = ["name", "url"]
df = pd.DataFrame(columns=columns) 

# 抽出したa要素を行列に入れ込む
for tag in tags:
    name = tag.string #　記事名の取得
    url = tag.get("href") #リンクの取得
    se = pd.Series([name, url], columns) # 行を追加
    print(se)
    df = df.append(se, columns)

# CSVに出力
filename = "topics.csv" # ファイル名の指定
df.to_csv(filename, encoding = 'utf-8') #csvへの変換、encoding指定(おまじない)
files.download(filename) # ダウンロード
```

# 補足
`from google.colab import files`これ自体はGoogle Colaboratoryで必要な機能っぽい。ローカルで動かすよう移行する時にどうなるか。
`filename`を宣言してファイル名を指定。変更や使い回しがしやすいようにしている。
encoding指定はよくわからないが必要らしい。

# 詰まったところ
特にエラーが出ていない状態で動かなかった。ダウンロードされない状態を繰り返し、原因がわからないためChromeを再起動したら解消した。
結局何が悪かったのかは分からずじまい。

# 次回への課題
- 法律周りの確認
- ~~CSVでダウンロード~~
- 1時間に1回取得などの動き
- 重複する内容を取得しないようにする
- 次ページ以降の取得
- 元リンクを取得
- ローカル環境で動かす
HTML DOM - 基本觀念 By 彭彭 18


	6. HTML DOM 處理網頁畫面的重要關鍵

![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/280122/a3c566b6-b375-018f-5d7e-f5e4dcca099b.jpeg)


```ruby
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"></meta>
	<title>HTML DOM</title>

	<script type="text/javascript">
	// 測試熒幕解析度 1536x864
	alert(window.screen.width + "x" + window.screen.height)
	function Change(){
		// 内建應用ElementById
		var spanObj = document.getElementById("emotion");
		spanObj.innerHTML = "悪いから、うちで寝る";
		// css的設置 改變顔色字體
		spanObj.style.color = "red";
		spanObj.style.fontweight = "bold";
		// 隱藏起來 display:none
		//spanObj.style.display = "none";
	}
	</script>

</head>
	<body>
		<div>
			<!-- 對畫面進行部分更新 -->
			天気が<span id = "emotion">いいから、散歩しましょう</span>
		</div>
		<button onclick = "Change();">Change</button>
	
	</body>
</html>
```
[Ruby][初心者] 可変長引数を受け取るメソッドを定義する

### 可変長引数

以下のように引数に*をつけることで複数の値を配列としてvaluesにいれてくれる

```ruby
def sum(*values)
  puts values.class
end

Array  # Arrayが出力されることから値が配列であることがわかる。

```

引数に渡した値を全て足した数を返すメソッド

```ruby
def sum(*values)
  values.inject { |total, n| total + n }
end

```

**と二つ書くことで値をハッシュ形式で受け取ることができる

```ruby
def some_method(**hash_values)
  puts hash_values
end

# 実行してみるとハッシュ形式で値が返ってきているのがわかる
some_method(param1: 'hoge', param2: 'fuga')
=> {:param1=>"hoge", :param2=>"fuga"}

```
MIT 单变量微积分メモ

導関数

```math
f'(x) = \frac{dy}{dx} = \lim_{△X \to 0} \frac{f(x+△X)-f(x)}{△X} \\

```


微分可能の定義

```math
x=aにおける　\lim_{△X \to 0} \frac{f(a+△X)-f(a)}{△X}　が存在すれば微分可能 \\ 

```


連続性の定義

```math
　\lim_{x \to a} f(x) = f(a) \\

```
微分可能と連続性の関係

　　X=aで微分可能ならx=aで連続、逆に連続でも微分可能とは限らない。

　　微分可能　→　左極限値　= 右極限値　→　連続

　　連続　→　左極限値　= 　右極限値　とは限らない　→　微分可能とは限らない


和の微分公式

```math
　 (a * f(x) + b * g(x))' = a* f'(x) + b * g'(x) 

```

積の微分公式

```math
  (f(x)* g(x))' = f'(x) * g(x) +  f(x) * g'(x)  

```

商の積分公式

```math

(\frac{f(x)}{h(x)})' = \frac{f'(x) * h(x) - f(x) * h'(x)}{h(x)^2}

```

合成関数の微分

```math
{f(g(x))}' = f'(g(x)) * g'(x)
```
理解しすいため

```math
\frac{dy}{dh} = \frac{dy}{dx} * \frac{dx}{dh}
```

高階微分

```math

f''(x) =  \lim_{△X \to 0} \frac{f'(x+△X)-f'(x)}{△X} \\ =  2\lim_{△X \to 0} \frac{ \frac{f(x+2△X)+f(x)}{2}-f(x+△X)}  {(△X)^2} \\

```
図の参照
http://www.phys.u-ryukyu.ac.jp/~maeno/sizensuugaku2016/lec9.html
babel-register を通して手動実行スクリプトの手軽さと flowtype の恩恵を両立させる

これまで `require` をフックしてしまう `babel-register` はなんとなく邪道ではと思って使っていなかったのですが、最近はよく flowtype を利用するようになり、いっぽうプロジェクト内の小さなツールを node で書くことが増えたこともあって、突然 register しましょうかという気持ちになりました。

いちいち型定義情報削除するために babel 通すのは面倒だし、コメント記法や別ファイル定義も flowtype の手軽さをスポイルしてしまうと感じていて、それであれば都度ビルド走ってもいいかなという。ただ、 `node -r babel-register` のようにコマンドラインに現れるのをやめたかったので、`require("babel-register")` で進めることにしました。

コードは以下で確認しています。

- node v10
- babel 7
- flow 0.79

※ babel 7 がリリースされました。

## 構成

インストールする。

```
$ npm init -y
$ npm install -D @babel/core @babel/register @babel/preset-flow \
                 @babel/preset-env flow-bin
$ npx flow init
```

手動実行するエントリポイントを `bin/` 以下に配置し、 実際のスクリプトの機能実装本体は `src/` 以下に置くとして、


```
$ tree . -I node_modules
.
├── bin
│   └── app.js
├── package-lock.json
├── package.json
└── src
    └── scripts
        └── app
            └── index.js

4 directories, 4 files
```

## 実装

エントリポイントとなるファイルは node 準拠で書く。`require("@babel/register")` 以降の require で babel での動的なコンパイルが行われます。ここでは、 `../src/scripts/app.js` が babel で処理されます。

```bin/app.js
// @flow
require("@babel/register");
const { app } = require("../src/scripts/app")

app()
```

src 以下のファイルは babel を通す前提で型定義もそのまま書いてしまう。普通のJSとしてはエラーになりますが、 `@babel/preset-flow` を通すことで型定義が無視されて素直に実行できるようになる寸法。

```src/scripts/app/index.js
// @flow
type LogicResult = {
  code: string
}

function logic(): LogicResult{
  return {
    code: "Success"
  }
}

export function app(){
  console.log(logic())
}
```

.babelrc には preset-env と preset-flow だけとりあえず設定している。

```json:.babelrc
{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-flow"
  ]
}
```

.flowconfig は生成されたときのまま。

```flowconfig:.flowconfig
[ignore]

[include]

[libs]

[lints]

[options]

[strict]
```
これでいつでも `node bin/app.js` できますし、`flowtype` の型チェックの恩恵も受けられます。

なお、flowによるチェックはコンパイル時に自動で走るわけではないので `npx flow check` 手動で叩く必要があります。このあたりは typescript の方が確実にチェックされるという意味では確実かなという気も。

なお、requireをフックしてビルドしている関係上遅いです。上記くらいの小さなコードでも

```
$ time node bin/app.js
{ code: 'Success' }

real	0m0.329s
user	0m0.295s
sys	0m0.051s
```

user 0.3秒くらいかかります。あくまでも「シェルスクリプトよりちょっとボータブルな自動化スクリプトを、静的型付けで書きたい or 業務ロジックとモデル共通化したい」みたいなケースで使える構成上の小技として考えたほうがよさそう。

本番系で使うバッチとか、npmモジュールの実行エントリポイントとして書くならちゃんとビルドしたものを使いましょうということで一つ。
bootstrap scrollspyが数値始まりのidの影響で誤動作していた

[bootstrapのscrollspy](https://getbootstrap.com/docs/4.1/components/scrollspy/)を使って、いい感じにマーカつけてやろう、
とか思ってたのに、一部のマーカ位置がハイライトされなかった話。

# だめな例

以下のようなHTMLを書く。
（bootstrapのサンプル改変）

```html
<div id="list-example" class="list-group">
  <a class="list-group-item list-group-item-action" href="#first">Item 1</a>
  <a class="list-group-item list-group-item-action" href="#second">Item2</a>
  <a class="list-group-item list-group-item-action" href="#3rd">Item 3</a>
  <a class="list-group-item list-group-item-action" href="#fourth">Item 4</a>
</div>
<div data-spy="scroll" data-target="#list-example" data-offset="0" class="scrollspy-example">
  <h4 id="first">Item 1</h4>
  <p>...</p>
  <h4 id="second">Item 2</h4>
  <p>...</p>
  <h4 id="3rd">Item 3</h4>
  <p>...</p>
  <h4 id="fourth">Item 4</h4>
  <p>...</p>
</div>
```

このとき、scrollspyを利用し、画面スクロールさせると

* first
    * activeつく
* second
    * activeつく
* 3rd
    * activeつかない
* fourth
    * activeつく

となる。


# 原因

bootstrap.jsを見てみる。

```javascript
      var _proto = ScrollSpy.prototype;
...
      _proto.refresh = function refresh() {
...
        this._targets = [];
        this._scrollHeight = this._getScrollHeight();
        var targets = [].slice.call(document.querySelectorAll(this._selector));
        targets.map(function (element) {
          var target;
          var targetSelector = Util.getSelectorFromElement(element);

          if (targetSelector) {
            target = document.querySelector(targetSelector);
          }
          if (target) {
              return オブジェクト（省略）
          }

          return null;
        })
```

と、

```javascript
          var targetSelector = Util.getSelectorFromElement(element);
```

でselectorを取得しに行っていて、
Util.getSelectorFromElementは

```javascript
      getSelectorFromElement: function getSelectorFromElement(element) {
        var selector = element.getAttribute('data-target');

        if (!selector || selector === '#') {
          selector = element.getAttribute('href') || '';
        }

        try {
          return document.querySelector(selector) ? selector : null;
        } catch (err) {
          return null;
        }
      },
```

のように

```javascript
selector = element.getAttribute('href') || '';
return document.querySelector(selector) ? selector : null;
```

としてselectorを確認する。

このとき、selectorが数値始まりだと、

```
VM8638:1 Uncaught DOMException: Failed to execute 'querySelector' on
 'Document': '#3rd' is not a valid selector.
```

のように怒られる。

これは、[CSSセレクタでは数値始まりのIDやクラスはNGだから](https://www.w3.org/TR/CSS22/syndata.html#characters)のようです。

```
In CSS, identifiers (including element names, classes, and IDs in selectors) 
can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+0080 
and higher, plus the hyphen (-) and the underscore (_); 
they cannot start with a digit, two hyphens, or a hyphen followed by a digit. 
```

ちなみにjQueryでは数値始まりのセレクタでも持ってきてくれた。
jQuery尊い。
*.lvh.meでSSL

## オレオレ証明書を作る

```
mkdir ssl
cd ssl
```

```
openssl req \
-newkey rsa:4096 \
-keyout lvh.me.key \
-x509 \
-nodes \
-new \
-out lvh.me.crt \
-subj "/CN=*.lvh.me" \
-reqexts SAN \
-extensions SAN \
-config <(cat /System/Library/OpenSSL/openssl.cnf \
<(printf '[SAN]\nsubjectAltName=DNS:lvh.me,DNS:*.lvh.me')) \
-sha256 \
-days 3650
```

## キーチェーンに登録する

### 1. 作成した`lvh.me.crt`を開く

```
open lvh.me.crt
```

### 2. キーチェーンアクセスで該当の証明書を選択しコンテキストメニューで「情報を見る」をクリック

<img src="https://qiita-image-store.s3.amazonaws.com/0/1172/24976d87-fc58-28da-34c9-aadca1831f28.png" width="700" /><img src="https://qiita-image-store.s3.amazonaws.com/0/1172/faf0a285-2af4-f804-0587-370a3a7400f9.png" width="150" />

### 3. 「:arrow_forward: 信頼」を開く

<img src="https://qiita-image-store.s3.amazonaws.com/0/1172/8cf993dc-7013-5c42-8b73-9e7dcb5c4f37.png" width="700" />

### 4. 「この証明書を使用するとき」を「常に信頼」へ変更

<img src="https://qiita-image-store.s3.amazonaws.com/0/1172/6aa7356a-9aa7-c10f-f349-1f5bd8df13da.png" width="700" /><img src="https://qiita-image-store.s3.amazonaws.com/0/1172/6790d64f-dffb-c254-1b82-6e6704045287.png" width="700" />

### 5. 開いているダイアログを閉じて、「証明書信頼設定に変更を加えようとしています。」で許可する。


<img src="https://qiita-image-store.s3.amazonaws.com/0/1172/62ea1553-423c-4f45-efe9-f817f3087fc5.png" width="300" />

## サンプルコード

```main.go
package main

import (
	"fmt"
	"net/http"
)

type myHandler struct{}

func (h *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello World!")
}

func main() {
	handler := &myHandler{}
	server := http.Server{
		Addr:    "127.0.0.1:8080",
		Handler: handler,
	}

	println(fmt.Sprintf("Listening on tcp://%s", server.Addr))
	server.ListenAndServeTLS("./ssl/lvh.me.crt", "./ssl/lvh.me.key")
}
```

```
go run ./main.go
```

```
Listening on tcp://127.0.0.1:8080
```

別コンソールで

```
open https://www.lvh.me:8080
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/1172/266ab47c-e543-81ec-ca66-b934549238c0.png" width="700" />

ワイルドカードの自己証明書なので、`https://hoge.lvh.me:8080`などでもよい。
VS Code 1.26 の新機能 - エディタグループの自動最大化

https://code.visualstudio.com/updates/v1_26#_grid-automated-maximize-of-minimized-editors

エディタグループを複数表示しているときに、１つのエディタグループを最大化すると、それ以降はエディタグループを切り替えた時にアクティブなエディタグループが自動的に最大化されるようになった。
![maximize.gif](https://qiita-image-store.s3.amazonaws.com/0/181011/a78293d3-95b4-d8f9-f2bf-9b44cc329691.gif)
コマンド: `表示: エディターグループを最大化`を使わなくても、手動でサイズを変更して最大化(か最大化に近い状態)してもこのモードになる。

このモードを解除したい場合は、コマンド: `表示: エディターグループのサイズをリセット`を使用するかエディタを閉じる。
【まとめ】MySQLコマンド Dash用スニペット


* [よく使うMySQLコマンド集 - Qiita](https://qiita.com/CyberMergina/items/f889519e6be19c46f5f4)
* [MySQLコマンドまとめ - Qiita](https://qiita.com/merrill/items/967884c02e10bd8f32f5)

ログイン。パスワード設定してるなら -p を付けパスワードを入力
`mysql -u __root__ -p`

ログイン（ルートで）
`mysql -uroot`

ログイン（リモートアクセス）
`mysql -h xxx.xxx.xxx.xxx -u __username__ -p`

場所確認 (例：/var/lib/mysql/)
`SHOW VARIABLES LIKE 'datadir';`

ユーザーの追加
`CREATE USER '__username__'@'__host_name|localhost__' IDENTIFIED BY '__password__';`

ユーザーにDB操作権限を付与
`grant all privileges on __db_name__.__*|table_name__ to '__username__'@'__host_name|localhost__'__ IDENTIFIED BY 'password'__;`
→ `flush privileges;`

ユーザーの権限を確認（for以降なければ現在のユーザー）
`show grants__ for 'user_name'@'host_name'__;`

ログイン中のユーザーのパスワードを設定
`set password = password('__password__');`

ユーザーのパスワードを設定
`update mysql.user set password=password('__password__') where user='__username__';`
→ `flush privileges;`

特定のユーザーのパスワードを設定
`set password for '__username__'@'__localhost__' = password('__password__');`

ユーザーを削除
`DROP USER __username__@__host_name__;`

ダンプ（バックアップ出力）
`mysqldump -u __username__ -p -x __--all-databases|database_name__ __table_name（無ければ全テーブル）__  __（条件指定なら）--where="id < 5"__ > __output_filename__.dump`

リストア（ダンプファイルから復元）
`mysql -u __username__ -p __new_db_name__ < __dump_file_name.dump__`


## データベースの操作

データベース一覧の表示
`SHOW DATABASES;`

データベースの追加
`CREATE DATABASE '__db_name__' DEFAULT CHARACTER SET utf8;`

データベースの選択
`USE __db_name__;`

データベースの削除
`DROP DATABASE __db_name__;`


## テーブルの操作

テーブル一覧の表示
`SHOW TABLES __STATUS__;`

カラムの表示
`SHOW FULL COLUMNS FROM __table_name__;`

ステータスを表示
`SHOW TABLE STATUS (like "table_name");`

画面幅より長い行を折り返さないよう別ビューで表示
`pager less -S;__qで抜ける。戻すには nopager__`

SQL実行結果をファイルに出力（シェル実行中）
`pager cat > /temp/mysql-dump.txt;`

SQL実行結果をファイルに出力
`-u root -p -e "select * from __table_name__" __db_name__ > /tmp/mysql-dump.txt`

テーブルの作成

```
CREATE TABLE __table_name__ (
  __field_name__ __TINYINT|INT|VARCHAR(99)|TEXT|BLOB|DATE|DATETIME__ __NOT NULL__ __AUTO_INCREMENT__ __PRIMARY KEY__ COMMENT "__説明__"
)__必要なら ENGINE=__InnoDB__ DEFAULT CHARSET=utf8__;
```

テーブルの削除
`DROP TABLE __table_name__;` 

テーブル構造の確認
`desc __table_name__`
`SHOW FULL COLUMNS FROM __table_name__;`


## レコードの操作

レコードの追加

```
INSERT INTO __table_name__ (
  __field1__, __field2__
) VALUES (
  __val1__,__val2__
);
```

レコードの更新

```
__【注意】条件式が無いと、全レコード対象となる__
UPDATE
  __table_name__
SET
  __field1__="__val1__", __field1__="__val1__"
WHERE
  __id = 5__;
```

レコードの削除

```
__【注意】条件式が無いと、全レコードが削除される__
DELETE FROM
  __table_name__
WHERE
  __id = 5 AND del_flg = 1__;
```


## その他

* `mysql --version` バージョン確認（簡易）
* `show status__ like "Threads_connected"__;` ステータス確認（like句無ければ全表示）
* `mysql.server start` 起動
* `mysql.server stop` 停止
* `show index from table_name;` インデックスを確認
「コミットする」と「プッシュ」の違い





よく分からなかったので、わかったことを備忘録的に書く。


　
　
**コミットとは、ファイルに関する記録のことである。**そして、コミットするとは、コミットを作成することを言う。


　
　
**プッシュとは、ローカルリポジトリ内[^1]の情報をリモートリポジトリへの反映させることである。**　　


　
　
以上！！！！！
　
　
（ぼくは「コミットする」と「プッシュ」がごちゃごちゃになっていた。）

[^1]: リポジトリとは、Gitがバージョン管理をおこなう際に保存する”箱”のようなもの。
Ruby—配列が別配列の要素を含むかどうかを判定する (配列同士を比較する)


```rb
# Both arrays has :C value
([:A, :B, :C] & [:C, :D, :E]).size > 0
# => true

# Both array has no same value
([:A, :B, :C] & [:D, :E, :F]).size > 0
# => false
```

## Versions

- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]


## Links

- [Gist](https://gist.github.com/YumaInaura/8204c34a17e1547274ff8907ca3759cf)
- [Medium—imported](https://medium.com/supersonic-generation/ruby-return-true-when-an-array-includes-some-element-in-other-array-elements-11a69d21bf12)








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
SQLZOO SELECT basics / SELECT from WORLD Tutorial 回答集

###＜2020/08/15 追記＞
現在、SQLの学習をSQLZOOで開始するのはあまりお勧めできません。
別のサービスの活用をご検討ください。

---

SQLの入門サイトとして名高いSQLZOOのチュートリアルより、
[「SELECT basics」](http://sqlzoo.net/wiki/SELECT_basics)と[「SELECT from WORLD Tutorial」](http://sqlzoo.net/wiki/SELECT_from_WORLD_Tutorial)の回答集を作成しました。

---
##[SELECT basics](http://sqlzoo.net/wiki/SELECT_basics)

1 . Introducing the world table of countries

```
SELECT population FROM world
  WHERE name = 'Germany'
```
>国名を書き換えるだけですね。

2 . Scandinavia

```
SELECT name, population FROM world
  WHERE name IN ('Sweden', 'Norway', 'Denmark')
```
>こちらも国名を書き換えるだけ。

3 . Just the right size

```
SELECT name, area FROM world
  WHERE area BETWEEN 200000 AND 250000
```
>数値を書き換えるだけです。

---
##[SELECT from WORLD Tutorial](http://sqlzoo.net/wiki/SELECT_from_WORLD_Tutorial)

1 . Introduction
>なにもしない

2 . Large Countries

```
SELECT name
  FROM world
 WHERE population >= 200000000
```
>比較演算子と数値の書き換え

3 . Per capita GDP

```
SELECT name, gdp/population
  FROM world
 WHERE population >= 200000000
```
>割り算で一人当たりGDPを算出

4 . South America In millions

```
SELECT name, population/1000000
  FROM world
 WHERE continent = 'South America'
```
>人口の100万単位表示とWHERE句の文字列指定

5 . France, Germany, Italy

```
SELECT name, population
  FROM world
 WHERE name IN ('France', 'Germany', 'Italy')
```
>IN句が初登場。()内のどれか、という意味。

6 . United

```
SELECT name
  FROM world
 WHERE name LIKE '%United%'
```
>Unitedは必ず先頭にくるので、'United%'でもよい。

7 . Two ways to be big

```
SELECT name, population, area
  FROM world
 WHERE area >=3000000 OR population >= 250000000
```
>millionは100万です。コンマ区切りできないので見づらい...

8 . One or the other (but not both)

```
SELECT name, population, area
FROM world
WHERE area >= 3000000 xor population >= 250000000
```
>排他的論理和というやつですね。いろんな方法があるのですが、一番簡単な「XOR」で表現しました。


9 . Rounding

```
SELECT name, ROUND(population/1000000, 2), ROUND(gdp/1000000000, 2)
FROM world
WHERE continent = 'South America'
```
>ROUND(数値, n)で小数点以下n桁に丸めます（四捨五入）。nは有効桁数と呼び、0が1の位、1が小数点以下第一位、-1が10の位です。
[ROUNDは色々オプションがあります](http://sql55.com/query/rounding.php)が、一旦無視して進んでいいでしょう。


10 . Trillion dollar economies

```
SELECT name, ROUND(gdp/population, -3)
FROM world
WHERE gdp >= 1000000000000
```
>さっそく有効桁数のマイナスが登場。

11 . Name and capital have the same length

```
SELECT name, capital
  FROM world
 WHERE LENGTH(name) = LENGTH(capital)
```
>LENGTH()で文字数を返します。

12 . Matching name and capital

```
SELECT name,capital
  FROM world
 WHERE LEFT(name,1) = LEFT(capital,1) and name <> capital
```
>

13 . All the vowels

```
SELECT name
  FROM world
 WHERE name LIKE '%a%' 
  and name LIKE '%i%' 
　and name LIKE '%u%'
  and name LIKE '%e%'
  and name LIKE '%o%'
   AND name NOT LIKE '% %'
``` 
>書き方汚くてすいません

---
####続きはこちら
https://qiita.com/TakahiroNAMBU/items/df954450b75b28c5853d
MetaMaskからローカルのGethに繋ごうとしてSynchronisation failed, dropping peerのエラーが出る

# 概要
Gethでローカルにメインネットのノードを立ててMetaMaskから繋ごうとしたら以下のエラーが出た。

```bash
WARN [08-18|09:38:09.835] Rolled back headers                      count=3    header=6166649->6166646 fast=0->0 block=0->0
WARN [08-18|09:38:09.835] Synchronisation failed, dropping peer    peer=bfad505cbb2bde72 err="action from bad peer ignored"
```

# 対応
別にMistを立ち上げていたので、それを閉じたら問題なくつなげる。
(GethはMist連携で立ち上げるのではなく別途立ち上げておく必要あり)

同じノードから複数のクライアントで繋ごうとすると起こる？ 詳細不明。

# 環境
- macOS High Sierra
- Geth/v1.8.13-stable-225171a4/darwin-amd64/go1.10.3
SQSに大量のキューが入ったらコンシューマーをオートスケールしたい

## やりたいこと

不定期でSQSにキューが登録され、コンシューマーのEC2にはバッチ処理がSQSのキューを常にポーリングしており、バッチ処理はデキューに成功したら業務処理を行います。

普段、起動しているコンシューマーのEC2は1台だけなので、プロデューサーが一度に大量のエンキューを行なった場合は、キューの数に比例した時間がかかります。しかし、大量のキューであったも、コンシューマーは全てのキューの処理を終えなくてはなりません。

Auto Scaling グループを作成してコンシューマーのEC2の台数を適宜調整すればいいのですが、手動でAuto Scaling グループの「希望」台数を調整するのは事故の元なので大量のキューが登録されたら、自動でスケールアウトして、未処理のキューがなくなったらスケール・インさせます。


## HOW TO

素直に公式ドキュメントに沿って設定します。

Amazon SQS に基づくスケーリング
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-using-sqs-queue.html

## キューの数に応じて、コンシューマーの台数を変更したい(ダメだった)
例えば、10,000以上のキューなら4台、20,000以上のキューなら8台、30,000以上なら12台といった要領で、オートスケールの台数を変えたいとおもいました。

### スケーリング調整タイプがExactCapacity の場合

ExactCapacityは スケールアウト後の台数を指定する方法です。
> 指定したインスタンス数にグループの現在の容量を変更します。この調整タイプには正の値を指定します。
> 例: グループの現在の容量が 3 インスタンスであり、調整値が 5 の場合、このポリシーが実行されると、容量は 5 インスタンスに設定されます。

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scaling-simple-step.html#as-scaling-adjustment より

プロデューサーが一度に大量のキューを登録した後に、CloudWatchのアラームが検知してスケールアウトしてEC2の台数が希望した通りになりました。

しかし、コンシューマーが処理を行い続け、キューの数が減り、一つ下のステップの範囲に達するとコンシューマーの数も減ってしまいました。例えば、 スケールアウトの開始時点ではキューの数が17,000件であれば、コンシューマーが8台になります。その後、キューの数が 10,000未満まで減ると下の4台に減りました。最後の0件になるまで8台で処理を行って欲しかったのです。

スケーリングポリシーは下の表の通りです。

| 追加/削除/設定 | 台数| 閾値下限 | メトリクス名 | 閾値上限 |
| ------------ | --- | ------- | --- |  ---------- | --- |  ------- | 
| 設定 | 1 | 1 | <= ApproximateNumberOfMessagesVisible < | 9999 |
| 設定 | 4 | 1000 | <= ApproximateNumberOfMessagesVisible < | 19999 |
| 設定 | 8 | 2000 | <= ApproximateNumberOfMessagesVisible < | 29999 |
| 設定 | 12 | 3000 | <= ApproximateNumberOfMessagesVisible < | 無限大 |


### スケーリング調整タイプがChangeInCapacity の場合

ChangeInCapacityは スケールアウト時に増やす台数を指定します。
> 指定したインスタンス数だけグループの現在の容量を増減させます。正の調整値は現在の容量を増やし、負の調整値は現在の容量を減らします。
> 例: グループの現在の容量が 3 インスタンスであり、調整値が 5 の場合、このポリシーが実行されると、グループに 5 インスタンスを追加して、合計で 8 インスタンスになります。

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scaling-simple-step.html#as-scaling-adjustment より

ExactCapacityのスケーリングポリシーを「設定」から「追加」に変更して試しました。プロデューサーが1,900のキューを登録した場合は4台増え、常に起動させている1台と合わせて5台になりました。その後クールダウンタイムが終わった時点で、キューの数が1,000 を超えていると、4台が追加で起動して合計9台になりました。その後も、同様に増え続けて Auto Scaling グループ の 最大キャパシティに達した所で、増えるのが止まりました。 

### 結局
プロデューサーが1回の処理で投入したキューの数に応じてコンシューマーの台数を固定することを諦め、常に最大キャパシティまでスケールアウトすることにしました。

断念した時に公式ドキュメントが簡易スケーリングポリシーを扱っている理由を理解しました。

実現するのであれば、プロデューサーがAuto Scaling グループの最大を調整する仕組みが必要そうです。
NetCommons3をPHP7.2以上の環境でインストールすると内部エラーになる


2018/08/18現在配布中の NetCommons3.1.10 をPHP7.2環境のサーバにインストールしようとすると、管理者アカウントを入力して送信した時点で「内部エラー」になってインストールが先にすすみません。

原因は単純で、CakePHP2のMigrationsプラグインで、PHPの予約語であるobjectと同名のクラスを利用してるから。

app/tmp/logs/error.log みると下記の様なエラーが記録されてるはずです。

```
 Fatal Error (64): Cannot use 'object' as class name as it is reserved in [/home/xxxx/NetCommons3/vendors/cakephp/cakephp/lib/Cake/Core/Object.php, line 18]
```

# Object から CakeObjectへ書き換える

問題のファイルは、 app/Plugin/Migrations/Lib/CakeMigration.php なのでこのファイルの1箇所を書き換えればインストールできるようになります。

17行目

```php
class CakeMigration extends Object {
```

↑ を ↓ に変更。

```php
class CakeMigration extends CakeObject {
```

Migrationsプラグインが対応してくれれば、一番いいんだけど https://github.com/CakeDC/migrations みてると更新とまってそうな気も…^^;
[Ruby] 後置if、後置unless

一行で条件分岐を書くために使われる

**if**

```ruby

country = 'ja'

'日本' if country == 'ja'
# 日本

'日本' if country == 'jp'
# nil
```

**unless**

```ruby

country = "us"

'その他の国' unless country == 'ja'
# その他の国

```
[Ruby] ヒアドキュメント

### ヒアドキュメントとは
複数行にまたがる長い文章の文字列を扱い場合に便利な機能

##### ヒアドキュメントのメリット
改行が保持される

```ruby

#　変数にヒアドキュメントを入れる
strings = <<EOS
 長い
  　　文章
　　   　です
EOS

＃ putsで出力すると改行が保持されてることがわかる
puts strings
 長い
　　　　　　文章
　　　　　　　　　　です
=> nil

```

ヒアドキュメントは文の先頭に書かないと行けないけど以下のようにすることでインデントを揃える場合などに対応できる

```ruby

  strings = <<-EOS
     長い
     文章
　    です
  EOS

# putsで出力すると改行が保持されてることがわかる
puts strings
 長い
　　文章
　　です
=> nil
```

EOSはEnd Of Stringの略、かならずしもEOSじゃなくてもいいらしい
ゲームAdventureをスマホに移植する2週目:CをC#に変換

# はじめに

これはアドベンチャーゲームの元祖「Colossal Cave Adventure」をUnityを使用してスマホに移植している作業ログです。
[1週目 解析編: Adventureのマスターデータを解析する](https://qiita.com/keidroid/items/b6a16c17474e6e83c6f1)
2週目 移植編: CのコードをC#に変換する ←今ここ

Colossal Cave Adventureプレイ画面
<img width="701" alt="スクリーンショット 2018-08-09 7.41.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/19692/8a40a0dc-aa97-5b5d-d7e2-dc2cce68e38e.png">


# 移植編

ゲームAdventureのコードはFORTRAN版とC版があるのですが、
どちらもUnityでは使用できないので数千行のCのコードをもくもくとC#へ移植しました。
今回はCのコードをC#に移植した手順を書きます。

<img width="1280" alt="スクリーンショット 2018-08-18 7.24.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/19692/169bd988-aa28-73b4-fbfc-1d5036976c00.png">

## 1.defineの移植

C#にdefineはないのでconstに変換しました。

方法 : C# で定数を定義する
https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/how-to-define-constants

```C
#define MAXTRS 79 
```

↓移植

```C#
public const int MAXTRS = 79;
```

## 2.typedefの移植

C#にtypedefはないのでusingを使用しました。

```C
typedef loc_t long;
```

↓移植

```C#
using loc_t = System.Int64;
```

## 3.関数の移植

Cなのでクラスはなく、共通ヘッダと各Cファイルに関数が分かれていました。
C#ではpartial型を使用して分割クラスとして移植しました。
変数名・メソッド名は他とかぶる可能性が大きいためnamespaceを定義しました。

partial (型) (C# リファレンス)
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/partial-type

```C:INIT.C 
void init() {
	//実際の処理
}
```

```C:DONE.C
void done(int entry) {
	//実際の処理
}
```

↓移植

```C#:Init.cs
//INIT.C
namespace Adventure {
	public partial class Game {
		void init() {
			//実際の処理
		}
	}
}
```

```C#:Done.cs
//DONE.C
namespace Adventure {
	public partial class Game {
		void done(int entry) {
			//実際の処理
		}
	}
}
```

## 4.変数・処理の移植

変数全般に関して、元コードは1978年制作という時代だけに現在とは方針が異なっていました。

元コードの方針

- 変数はローカル定義よりなるべくグローバル定義で行う
- 変数名はなるべく略す

現在の(一般的な)方針

- 変数はグローバル定義よりなるべくローカル定義で行う
- 変数名はなるべく略さない

また、以下の変数名が使われていたのですが、予約語で使用できないため変更しました。

```
fixed, break, throw
```


ゲームAdventureで使用されている略された変数名で、
パッと見わからなかったものを以下に挙げます。

|名称|説明|
|:--|:--|
|e|東|
|w|西|
|n|北 (ne, nwもあり). もしくはYESNOでのNOを表す|
|s|南 (se, swもあり)|
|u|上|
|d|下|
|cond|CONDition? 条件に使用する状態ビット|
|lit|LighT|
|liq|LIQuid|
|obj|OBJect. RPGのイベント全般(アイテム, 敵, スイッチetc..)を指している|
|invent|INVENTory. アイテムのこと|
|trs|TReaSure. おたからアイテムのこと|
|loc|LOCation. SECTION:1を参照|
|cval|Class VALue.  c*は階級に関する変数. 階級とは探検終了時にされる評価のこと|
|dflag| Dwarf FLAG. d*はドワーフに関する変数|
|odloc|Old Dwarf LOCation. od*もドワーフに関する変数|
|hcave|洞窟に関するヘルプ. h*はヘルプに関する変数|
|fixed|objの状態がはいる|
|plac|objの移動元がはいる. 4文字に略した変数はobjの場所系変数というルール?|
|fixd|objの移動先がはいる. 4文字に略した変数はobjの場所系変数というルール?|
|pspeak|テキスト処理で先頭pのときはParagraph?Page?(SECTION:1)を指している|
|rspeak|テキスト処理で先頭rのときはaRbitary(SECTION:6)を指している|
|mspeak|テキスト処理で先頭mのときはMagic(SECTION:12)を指している|
|weq|Word EQualの略|
|ran|RANdomの略|
|rnum|Read NUMber. 指定のマスターデータのキーIDを指している|
|pct|PerCenT. 百分率を指している|
|k|ただのtmp変数. 複数用途に使用しているので一概に言えない. kk, k2, kpも同様|
|spk|SPeaK|
|prop|PROPerty. ゲーム内の状態.|
|y2|ゲーム内で使用する固有名詞|
|foo|ゲーム内で使用する固有名詞|

# つづく
お盆なのであまり時間取れませんでしたがロジックは移植完了。
来週はCUIゲームのAdventureをUnity上(GUI)で動作させる予定です。
[Ruby] Rangeオブジェクトについて

### Rangeオブジェクト

rangeを作成

```ruby

1..3
# 1..3

(1..3).class
# Range
```


to_aで変換してみるとどんなものかわかりやすい

```ruby

(1..3).to_a
# [1, 2, 3]
```

..だと書いた通りの範囲を表す、...だと最後の数字は含まないRangeを返す

```ruby

(1..3).to_a
# [1, 2, 3]

(1...3).to_a
# [1, 2]
```

アルファベットの並びを作ることもできる

```ruby

('a'..'z').to_a
# ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
```
[Ruby] Hashオブジェクト 値を削除する

### ハッシュオブジェクトの値の削除の仕方

Hashを作る

```
user = {
  name: 'tarou',
  age: 29,
  race: 'caucasian'
}
```

deleteメソッドに削除対象のキーを指定することで削除できる
戻り値は削除されたキーに対応する値になる

```
user.delete(:race)
=> "caucasian"
```
[Ruby] Hashのvalues、keys

### Hashオブジェクトkeys、valuesメソッド

ハッシュオブジェクトはvaluesとkeysというメソッドを持っている

- keys  　キーを配列で返す


- values  　　ハッシュの値を配列で取得する

```
user = {
  name: '太郎',
  tests: {
    math: 90,
    english: 70,
    science: 20
  }
}

user.keys
=> [:name, :tests]

user.values
=> ["太郎", {:math=>90, :english=>70, :science=>20}]
```
[Ruby] Arrayを楽に書く %記法

### Arrayを%記法で書く
ArrayやHashを''(シングルクオート)で囲ったり、,(カンマ)で区切ったりしなくていいのでスッキリかける


```
%w[hoge fuga piyp]
=> ["hoge", "fuga", "piyo"]
```

大文字で書くと""(ダブルクオート）で囲ったのと同じ意味になり式展開ができる

```
変数を定義
hoge = 'hoge'

小文字だと展開できない
%w[#{hoge} fuga piyp]
=> ["#{hoge}", "fuga", "piyo"]

大文字だと展開できる
%W[#{hoge} fuga piyp]
=> ["hoge", "fuga", "piyo"]

```

[]で囲んでいる部分は、!!とかでもいいけど基本[]で書くらしい

```
%W!#hoge} fuga piyp!
```

シンボルの配列を作る場合は **%i** を使う

```
%i[hoge fuga piyo]
=> [:hoge, :fuga, :piyo]
```

####おわり
最近JSばかり書いていてRubyを忘れてきていたので復習がてら勉強しています。
詳解 CNNLDR 3.3

#背景

　Deep Learning では計算精度をある程度落としても推論精度に大きく影響を与えることなく動作することが知られており、各種小ビットでの実験が行われています。特に ["Convolutional Neural Networks using Logarithmic Data Representation"](https://arxiv.org/abs/1603.01025) では、重みやアクティベーションを5ビットの対数で表現し、FP32とさほど変わらない推論精度を達成しています。

　対数を用いた場合、乗算を加算で置き換えられる利点があり、これは計算回路上に**乗算器を必要としない**ことを意味します。

　対数ベースで考えた場合、積和演算で考えなければならないなのは乗算よりもむしろ加算であり、つまり$\log(a+b)$  をどう計算するか、です。対数の性質として、指数法則より
$$\log ab = \log a +\log b$$
 が成り立つことは広く知られていますが、
$$\log(a+b)$$
の効果的な計算方法はあまり知られていません。

　Miyashitaらは上記論文中 **3.3. Accumulation in log domain** （以下、**CNNLDR 3.3**）において下記図のような近似的計算方法を提案していますが、対数の計算に詳しい者でないと理解は難しいと思いました。（少なくとも私は苦労しましたｗ）この文章ではその計算方法について詳しく解説します。

![CNNLDR3.3.png](https://qiita-image-store.s3.amazonaws.com/0/119039/4e43c734-0c76-6daa-60a7-16a04d8cedcc.png) 

#解説
##前提
まず、

```math
a+b = a\times (1+\frac{b}{a}) \tag{1}\\
ただし　0 < b \le a
```
とする。すると $ 1 < n $ について

```math
\begin{align}

\log_n(a+b) &=\log_n(a \times (1+\frac{b}{a})) \\
&=\log_n a + \log_n(1+\frac{b}{a}) \\
&=\log_n a + \log_n(1+n^{\log_n b - \log_n a}) \tag{2}\\
\end{align}
```
底が $2$ かつ $ 0 \leq X \leq 1 $ のとき

```math
\log_2(1+X)\simeq X  \tag{3} \\
``` 
と近似できる。(下記グラフを参照)

![log2(x):x_chart.png](https://qiita-image-store.s3.amazonaws.com/0/119039/6ce22ab1-e315-a777-20df-aa265ba65dde.png)

また、$(1)$ の条件より

```math
0 < \frac{b}{a}  = n^{\log_n b - \log_n a} \leq 1\\
```

よって $(2)$, $(3)$ より

```math
\begin{align}
\log_2 (a+b)
 &\simeq \log_2 a + 2^{\log_2 b - \log_2 a} \tag{4}\\
\end{align}
```
##近似式の導出

**CNNLDR 3.3** における定義より

```math
\begin{align}
\tilde{s}_2 &= \log_2(s_2) \\
&= \log_2(w_1x_1 + w_2x_2) \\
&= \log_2(2^{\log_2 w_1 + \log_2 x_1}+2^{\log_2 w_2 + \log_2 x_2}) \tag{5}\\
&= \log_2(2^{{\tilde{w}_1}+{\tilde{x}_1}}+2^{{\tilde{w}_2}+{\tilde{x}_2}}) \\
&= \log_2(2^{\tilde{p}_1} + 2^{\tilde{p}_2}) \\
\end{align}
```
となり、$(4)$ より

```math
  \tilde{s}_2 \simeq \tilde{p}_1 + 2^{{\tilde{p}_2}-{\tilde{p}_1}}
```
と近似できる。これはコンピュータ上では

```math
 \mathrm{max}({\tilde{p}_1}, {\tilde{p}_2}) + \mathrm{Bitshift}(1, -|{\tilde{p}_2} - {\tilde{p}_1}|)
```
と計算できる。解説終わり。
***
底が $ \sqrt{2} $ のとき、$(3)$は

```math
\log_\sqrt{2}(1+X) \simeq 2X \tag{3'}
```

<!--
```math
\begin{align}
\tilde{s}_2 &= \log_\sqrt{2}(\sqrt{2}^{\tilde{p}_1} + \sqrt{2}^{\tilde{p}_2}) \\

\end{align}
```

```math
\begin{align}
\tilde{s}_2 &\simeq \tilde{p}_1 + 2 \cdot \sqrt{2}^{\tilde{p}_2 - \tilde{p}_1} \\
&= \tilde{p}_1 + 2^1 \cdot 2^\frac{\tilde{p}_2 - \tilde{p}_1}{2}
\end{align}
```
-->
近似式：

```math
\mathrm{Bitshift}\bigl(\mathrm{max}(\tilde{p}_1, \tilde{p}_2) + \mathrm{Bitshift}(1, -|\tilde{p}_2 - \tilde{p}_1|), 1 \bigr)
```
visualizeMessageMap

addEventListenerによって操作されるmapと{selector, its parameters}のmapはどこにあるんだっけ? と 考えた．

https://tuhrig.de/messages-vs-events-vs-commands/

どこにあるのかという疑問はググれば，ぼんやりとは判る．

狙いはそれらのmapの可視化．

それらのmapを可視化するにはどうすればいいのか?

1. public methodをreceive(message)のみとする
2. protected Map\<Message, function\> mmを定義．functionはprivate method

```

mm = {
    {{selector: "transit"}, this.transit},
    {{type: "double clicked"}, this.hide},  
};

receive = (message) => {
    var f, lop;
    if (this.mm.contain(message)) {
        // TODO: To implement accessor 4 mm.
        if (message is Command) {
            f = this.mm[message.selector];
            lop = message.parameters;
            f(lop);
        } else if (message is Event) {
            // omitted.
        }
    }
}

//----------------------------------------
// private
//----------------------------------------
transit = (lop) => {
}

hide = (lop) => {
}
【初心者向け】Rails API を活用していますか？

# Rails の取り扱い説明書、それが Ruby on Rails API

みなさんこんにちは！

突然ですが、あなたは [Ruby on Rails API](http://api.rubyonrails.org) を知っていますか？

「API」というのは「プログラムの取り扱い説明書」のことです。
なので、「Ruby on Rails API」は「Railsの取り扱い説明書」のことを表します。もっと簡単に言えば、Railsの公式ドキュメントです。

ある程度 Rails を使っている人なら、みんな知っているレベルのものですが、ちゃんと紹介している記事が意外と見当たらなかったので、紹介記事を書いてみることにしました。

# Ruby on Rails API に書いてあること

Rails が独自に定義している、クラスやメソッド（例えば `ActionController::Base` や `link_to` など）について、以下のような情報を得ることができます。

* 概要（何をするためのものか？）
* メソッドの引数や戻り値
* サンプルコード
* 使用上の注意点

例えば、`default_scope` というメソッドを API で検索した場合、以下の情報が表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/187987/ad7aecc2-5961-2f37-2ee2-8d03de00a4ed.png)

* モデルに対して、デフォルトの検索条件を設定できる
* モデル内で `default_scope { where(published: true) }` のように記述する
* レコードの新規作成時のデフォルト値にも影響を与える

といったことが書いてあります。サンプルコードなども記述されていて、とても分かりやすいですね。

# Ruby on Rails API の使い方

使い方はとても簡単です。
http://api.rubyonrails.org にアクセスし、

1. 左上の検索フォームに、メソッド名やクラス名を入力します。
2. 左下に候補が表示されるので、詳しく見たいものを選択します。
3. 右側に、メソッドまたはクラスの詳細が表示されます。

![スクリーンショット 2018-08-18 1.28.05.png](https://qiita-image-store.s3.amazonaws.com/0/187987/2a056c27-49fd-f67c-16e9-79914e8486de.png)

実際に使って見ると分かりますが、レスポンスが非常に早く、とても快適です。


# 過去バージョンの API も見れる！

http://api.rubyonrails.org には、常に最新バージョンの API が表示されます。
記事執筆時点では Rails 5.2.1 です。
![スクリーンショット 2018-08-18 1.56.06.png](https://qiita-image-store.s3.amazonaws.com/0/187987/af658176-fdab-c1ba-892c-1dcd7ea29a56.png)

でも、実際の開発では、常に最新バージョンの Rails が使えるわけじゃないですよね。旧バージョンの API を見ることはできないのでしょうか？ ええ、もちろん見れます。

http://api.rubyonrails.org/v4.2.9 のように、URL の末尾に `v + バージョン番号` をつければ良いんです！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/187987/71f14c2f-1742-6476-6add-25e8f60d89ea.png)

自分のプロジェクトで使っているバージョンのURLを、ブックマークに登録しておくと便利です。


# まとめ

* **Ruby on Rails API** とは、Railsの取り扱い説明書である。
* メソッド名やクラス名から検索できる。
* 過去バージョンの情報を見ることもできる。


# おまけ

`Source: show | on GitHub` のリンクから、気軽にソースコードを確認できるので、暇な時にやってみてください。
名前の付け方や、メソッドの分け方、コメントの使い方など、とても勉強になります。
また、Railsが内部でどんな処理をしているのか理解することで、デバッグなどにも活かせます。
![スクリーンショット 2018-08-18 3.48.00.png](https://qiita-image-store.s3.amazonaws.com/0/187987/2341bb52-f84a-6fac-ceaf-84e51926c754.png)