rails hands on

# rails で Web アプリを作ってみよう！

Web アプリを作って、動かして、触って、デプロイしてみよう！

## 事前準備

`docker` , `bundler` はインストールしておいてね

### docker

- 公式
    - [Install Docker Desktop for Mac \| Docker Documentation](https://docs.docker.com/docker-for-mac/install/)
- Mac の人は
    - [DockerをHomebrewでMac OSに導入する方法 \- Qiita](https://qiita.com/sitmk/items/ed753f6b2eb9960845f7)

### bundler

- 公式
    - [Bundler: The best way to manage a Ruby application's gems](https://bundler.io/)
- Mac の人は
    - [MacにHomeBrew,rbenv,bundlerをインストールする \- Qiita](https://qiita.com/shinkuFencer/items/3679cfd966f6a61ccd1b)

### 他

[docker-compose.yml](https://www.dropbox.com/s/rzemjtmn0ji7deo/docker-compose.yml?dl=0)
[Dockerfile](https://www.dropbox.com/s/fom01ew5nvgnfnw/Dockerfile?dl=0)
[docker](https://www.dropbox.com/sh/nist1ke2mychs4d/AABma93NyIVHstruDj7lTf_Ya?dl=0)

をローカルにコピー
TODO: curl でダウンロードできるようにする

## やってみよう！

```sh
$ mkdir rails_sample && cd rails_sample
$ cp -a ~/Download/Dockerfile ~/Download/docker-compose.yml ~/Download/docker .
remove `Gemfile.lock` in Dockerfile
$ bundle init
$ docker-compose run --rm web bundle exec rails new . -d mysql --skip-test
```

ここで今日のゴールを
https://rails-sample-fot-lt.herokuapp.com/users/sign_in
（今日はログインやらんけど）

ログインあり＆デプロイありの、ハンズオンやりたいと思う人！

希望あれば日程調整しましょう
3時間ぐらい
うまくいけば30分

edit database.yml

```sh
  pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %>
  username: <%= ENV.fetch('MYSQL_USERNAME') { 'root' } %>
  password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %>
  host: <%= ENV.fetch('MYSQL_HOST') { '127.0.0.1' } %>
  port: <%= ENV.fetch('MYSQL_PORT') { 3306 } %>
```
add `Gemfile.lock` in Dockerfile

```sh
$ docker-compose up
$ docker-compose exec web bin/rails g scaffold post content
$ docker-compose exec web bin/rails db:migrate
```

## hands on メモ


```sh
$ mkcd rails_sample
$ cp -a ~/Download/Dockerfile ~/Download/docker-compose.yml ~/Download/docker .
```

remove `Gemfile.lock` in Dockerfile

```sh
$ bundle init
$ docker-compose run --rm web bundle exec rails new . -d mysql --skip-test
create remote repository
$ cp -a ~/Download/Gemfile  .
```

edit database.yml

```yml:database.yml
  pool: <%= ENV.fetch('RAILS_MAX_THREADS') { 5 } %>
  username: <%= ENV.fetch('MYSQL_USERNAME') { 'root' } %>
  password: <%= ENV.fetch('MYSQL_PASSWORD') { 'password' } %>
  host: <%= ENV.fetch('MYSQL_HOST') { '127.0.0.1' } %>
  port: <%= ENV.fetch('MYSQL_PORT') { 3306 } %>
```

add `Gemfile.lock` in Dockerfile

```sh
$ docker-compose up
$ docker-compose exec web bundle install
$ docker-compose exec web rails generate simple_form:install
$ docker-compose exec web rails haml:erb2haml
$ docker-compose exec web rails g annotate:install
$ docker-compose exec web bin/rails g scaffold post content
$ docker-compose exec web bin/rails g scaffold user name
$ docker-compose exec web bin/rails db:migrate
$ docker-compose exec web bundle exec rails generate devise:install
```

add

```haml
    %p.notice= notice
    %p.alert= alert
```
in app/views/layouts/application.html.haml

```
$ docker-compose exec web bundle exec rails g devise:views
$ docker-compose exec web rails generate devise user
$ docker-compose exec web bin/rails db:migrate
```

add `before_action :authenticate_user!` in app/controllers/posts_controller.rb and app/controllers/users_controller.rb

add `root to: 'post#show'` route.rb

access http://localhost:3000/users

### heroku deploy
create app in gui

```sh
$ heroku login
$ heroku git:remote -a rails-sample-fot-lt
$ git push heroku master
$ heroku addons:create cleardb:ignite
$ heroku config | grep CLEARDB_DATABASE_URL

mysql://[username]:[password]@[hostname]/[db_name]?reconnect=true

$ heroku config:add DB_NAME="[db_name]"
$ heroku config:add DB_USERNAME="[username]"
$ heroku config:add DB_PASSWORD="[password]"
$ heroku config:add DB_HOSTNAME="[hostname]"
$ heroku config:add DB_PORT="3306"
$ heroku run rake db:migrate
```

---
コピー用


```dockerfile:Dockerfile
FROM ruby:2.6.2

RUN apt-get update --fix-missing \
  && apt-get -y upgrade \
  && apt-get install -qq -y \
    nodejs \
    mysql-client \
  && apt-get autoremove -y \
  && apt-get clean all \
  && fc-cache -f -v

# Add dumb init to process system events
RUN wget https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 -O /usr/local/bin/dumb-init
RUN chmod +x /usr/local/bin/dumb-init

RUN gem update --system
RUN gem install bundler

WORKDIR /rails_sample
COPY Gemfile Gemfile.lock ./
RUN bundle install --jobs=4 --retry=3

COPY . .

EXPOSE 3000

# Start the main process.
CMD bin/rails server -b 0.0.0.0
```

```yml:docker-compose.yml
version: '3.7'

services:
  db:
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 3306:3306
    volumes:
      - ./docker/mysql/conf:/etc/mysql/conf.d:rw
      - dbdata:/var/lib/mysql

  web:
    build: .
    depends_on:
      - db
    volumes:
      - .:/rails_sample
      - "bundle:/usr/local/bundle"
    environment:
      - MYSQL_HOST=db
    command: >
      bash -c "
        bundle install --quiet &&
        docker/bin/start rails"
    ports:
      - 3000:3000

volumes:
  bundle:
  dbdata:
```

```shell:docker/mysql/conf/default_authentication.cnf
[mysqld]
default_authentication_plugin=mysql_native_password
```

```shell:docker/bin/rails
#!/bin/sh

docker-compose run --rm backend bin/rails "$@"
```

```shell:docker/bin/start
#!/bin/sh

if [ $# = 0 ]; then
  echo "usage:"
  echo "  start rails:              Start rails server"
  echo "  start rails recreate db:  Start rails server recreate db"
  echo "  start sidekiq:            Start sidekiq process"
  echo "  start sidekiq-web:        Start sidekiq web server"
  exit 1
fi

case "$1" in
  "rails")
    bundle exec rails tmp:pids:clear
    bundle exec rails log:clear tmp:clear
    bundle exec rails server --port 3000 --binding "0.0.0.0"
    ;;
  "rails recreate db")
    bundle exec rails tmp:pids:clear
    bundle exec rails db:reset
    bundle exec rails db:migrate
    bundle exec rails log:clear tmp:clear
    bundle exec rails server --port 3000 --binding "0.0.0.0"
    ;;
  "rails migrate db")
    bundle exec rails db:migrate
    ;;
  "sidekiq")
    bundle exec sidekiq
    ;;
  "sidekiq-web")
    bundle exec rackup --host "0.0.0.0" --port 9292 lib/sidekiq_web/config.ru
    ;;
esac
```