【Rails】MySQLによる開発

今までいくつかWebアプリケーションを制作したり学習をしてきましたが、
MySQLを使用することがありませんでした。

今回新しくアプリケーションを制作する上で本番環境をAWS＋MySQLを使用して開発をしてみようと思います！
まだまだ初心者なので、間違っているところがあればご指摘お願いします。

#MySQLとは
世界で最も利用されているデータベースで、以下のような特徴があります。

* 大容量のデータベースを高速かつ安定的に利用できる
* 関連のあるデータ項目が、事前に定義されている
* データベースは、テーブル単位にデータを保持し、テーブル間の関係も保持する
* データ項目は列として表現され、関連のあるデータ項目の集合体が行として表現されたテーブルが形成される（Excelのタイトル付きの表のようなイメージ）
* リレーショナルデータベースとのやりとりには、SQLが使用される
* 日本語に対応している

#SQLiteとの違い
Railsをインストールして、デフォルトで使用されるRDBMSは**SQLite**
SQLiteは以下のような特徴がある

* それほど大きなデータベースではなく、個人利用レベルのデータベースの利用を想定している
* リレーショナルデータベースとのやりとりには、SQLが使用される
* 著作権が放棄されパブリックドメインで誰もが自由に利用できる
* 消費メモリも少ないため、処理能力が低い小型デバイスでも組み込める

巨大なDBを扱う場合はMySQLを使用した方が良いらしい

#MySQLで開発をしてみる

##Mac へ MySQL をインストール
まずはMacにMySQLをインストールします！

下記記事を参考にインストール！
[Mac へ MySQL を Homebrew でインストールする手順](https://qiita.com/hkusu/items/cda3e8461e7a46ecf25d )

####下記コマンドでインストール
```
$ brew update
$ brew install mysql
```

####インストールができているか確認
```
$ brew info mysql

mysql: stable 8.0.22 (bottled)
Open source relational database management system
https://dev.mysql.com/doc/refman/8.0/en/
Conflicts with:
  mariadb (because mysql, mariadb, and percona install the same binaries)
  percona-server (because mysql, mariadb, and percona install the same binaries)
/usr/local/Cellar/mysql/8.0.22 (294 files, 296.5MB) *
  Poured from bottle on 2020-11-04 at 13:55:11
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/mysql.rb
License: GPL-2.0
==> Dependencies
Build: cmake ✘
Required: openssl@1.1 ✔, protobuf ✔
==> Caveats
We've installed your MySQL database without a root password. To secure it run:
    mysql_secure_installation

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -uroot

To have launchd start mysql now and restart at login:
  brew services start mysql
Or, if you don't want/need a background service you can just run:
  mysql.server start
==> Analytics
install: 85,249 (30 days), 214,834 (90 days), 813,126 (365 days)
install-on-request: 83,371 (30 days), 209,508 (90 days), 784,193 (365 days)
build-error: 0 (30 days)
```
バージョン8.0.22がインストールされていた！

####MySQLを起動してみる
```
$mysql.server start
Starting MySQL
 SUCCESS! 
```

####接続して動作確認をしてみる
```
$mysql -uroot

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
```
・・・・エラー（泣）
パスワードがないのでダメみたいですね！
設定します！

##セキュリティ設定

```
$mysql_secure_installation

Enter password for user root:（パスワードを入力する）
```

パスワードの強度をチェックしてくれるプラグインのセットアップをする？「y」

```
VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No: y
```

検証レベルを選ぶ。

```
There are three levels of password validation policy:

LOW    Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2
```

* LOW：8文字以上
* MEDIUM：8文字以上 ＋ 数字・アルファベットの大文字と小文字・特殊文字を含む
* STRONG：8文字以上 ＋ 数字・アルファベットの大文字と小文字・特殊文字を含む ＋ 辞書ファイルでのチェック

本番環境ようなので、２を選択。
先ほど入力したパスワードの強度が合致していないと再度入力を求められます。
２度パスワードを打ち込むと、これで確定していいんだね？と言われるので「y」

```
Estimated strength of the password: 50 
Change the password for root ? ((Press y|Y for Yes, any other key for No) : y

New password: 

Re-enter new password: 
Estimated strength of the password: 100 
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y
```

匿名ユーザ（ anonymous user ）を削除する？「y」

```
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.
```

リモートから root ユーザでログインできないようにします。ログインを禁止する?「y」

```
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.
```

デフォルトで作成されている test という名前のデータベースを削除する?「y」

```
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.
 - Removing privileges on test database...
Success.
```

すぐに権限テーブルをリロードして変更を有効にする?「y」

```
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done! 
```

とりあえず、設定はできたかな？

####もう一度動作確認

```
$mysql -u root -p
Enter password:（パスワード入力）

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.32 Homebrew

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```
動いた！:)

```
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)
```

testデータベースも無くなっていました！

一度mysqlからはexitして・・・
停止もして・・・

```
$ mysql.server stop
Shutting down MySQL
. SUCCESS! 
```

#アプリ立ち上げ！
RailsはデフォルトではSQLiteを使用するため、
MySQLを使用するためには立ち上げの際に指定してあげる

```
rails new アプリケーション名 --database=mysql
```

省略もできる

```
rails new アプリケーション名 -d mysql
```

こうすることで、RDBMSをMySQLに変更することができるらしい。
念のためGemfileを確認・・・
指定しない場合は

```ruby:Gemfile
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
```

となるのに対して、指定してあげると

```ruby:Gemfile
# Use mysql as the database for Active Record
gem 'mysql2', '>= 0.3.18', '< 0.5'
```

となりました！！

しかし`bundle install`してもエラーが発生・・・

```
・
・
（たくさんのログ）
・

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2
/Users/mariko/.rbenv/versions/2.6.5/bin/ruby -I /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/2.6.0 -r ./siteconf20201104-33105-i9fwuc.rb extconf.rb
checking for rb_absint_size()... yes
checking for rb_absint_singlebit_p()... yes
checking for rb_wait_for_single_fd()... yes
-----
Using mysql_config at /usr/local/opt/mysql@5.7/bin/mysql_config
-----
checking for mysql.h... yes
checking for errmsg.h... yes
checking for SSL_MODE_DISABLED in mysql.h... yes
checking for SSL_MODE_PREFERRED in mysql.h... yes
checking for SSL_MODE_REQUIRED in mysql.h... yes
checking for SSL_MODE_VERIFY_CA in mysql.h... yes
checking for SSL_MODE_VERIFY_IDENTITY in mysql.h... yes
checking for MYSQL.net.vio in mysql.h... yes
checking for MYSQL.net.pvio in mysql.h... no
checking for MYSQL_ENABLE_CLEARTEXT_PLUGIN in mysql.h... yes
checking for SERVER_QUERY_NO_GOOD_INDEX_USED in mysql.h... yes
checking for SERVER_QUERY_NO_INDEX_USED in mysql.h... yes
checking for SERVER_QUERY_WAS_SLOW in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_ON in mysql.h... yes
checking for MYSQL_OPTION_MULTI_STATEMENTS_OFF in mysql.h... yes
checking for my_bool in mysql.h... yes
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
-----
Setting libpath to /usr/local/opt/mysql@5.7/lib
-----
creating Makefile

current directory: /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2
make "DESTDIR=" clean

current directory: /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2
make "DESTDIR="
compiling client.c
compiling infile.c
compiling mysql2_ext.c
compiling result.c
compiling statement.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3 for inspection.
Results logged to /Users/mariko/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/extensions/x86_64-darwin-19/2.6.0/mysql2-0.5.3/gem_make.out

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

In Gemfile:
  mysql2
         run  bundle binstubs bundler
Could not find gem 'mysql2 (>= 0.4.4)' in any of the gem sources listed in your Gemfile.
         run  bundle exec spring binstub --all
Could not find gem 'mysql2 (>= 0.4.4)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.
       rails  webpacker:install
Could not find gem 'mysql2 (>= 0.4.4)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.
```

下記記事を参考に進めました！
[【Rails】MySQL2がbundle installできない時の対応方法](https://qiita.com/fukuda_fu/items/463a39406ce713396403)

```
$ brew info openssl
openssl@1.1: stable 1.1.1h (bottled) [keg-only]
Cryptography and SSL/TLS Toolkit
https://openssl.org/
/usr/local/Cellar/openssl@1.1/1.1.1g (8,059 files, 18MB)
  Poured from bottle on 2020-05-21 at 18:53:48
/usr/local/Cellar/openssl@1.1/1.1.1h (8,067 files, 18.5MB)
  Poured from bottle on 2020-11-01 at 12:26:48
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openssl@1.1.rb
License: OpenSSL
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl@1.1/certs

and run
  /usr/local/opt/openssl@1.1/bin/c_rehash

openssl@1.1 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.

If you need to have openssl@1.1 first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> /Users/mariko/.bash_profile

For compilers to find openssl@1.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
  export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"

For pkg-config to find openssl@1.1 you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"

==> Analytics
install: 835,013 (30 days), 1,906,254 (90 days), 7,237,126 (365 days)
install-on-request: 136,062 (30 days), 257,990 (90 days), 1,007,070 (365 days)
build-error: 0 (30 days)
```

この部分が重要らしい。

```
export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
export CPPFLAGS="-I/usr/local/opt/openssl@1.1/include"
```

下記の二つのコマンドを実行

```
$ bundle config --local build.mysql2 "--with-cppflags=-I/usr/local/opt/openssl@1.1/include"
You are replacing the current local value of build.mysql2, which is currently nil

$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl@1.1/lib"
You are replacing the current local value of build.mysql2, which is currently "--with-cppflags=-I/usr/local/opt/openssl@1.1/include"
```

再度bundle install
インストールできました・・・・・！！！嬉泣

#まとめ
アプリにMySQLを導入するまでかなり右往左往してしまいました。
読みづらかったらすみません。
少しでも誰かのお力に慣れたら嬉しいです。

参考にさせていただいた筆者の方々、本当にありがとうございました。

途中でSQLiteに変更する手順もあるみたいなので、今まで制作したアプリで試してみようと思います。