【個人学習振り返り】Ruby on Rails 勉強 #1

#■この記事の目的
自分の振り返り用としての投稿です。
Sierから卒業しWebエンジニアになるため、Rubyを１から習得中です。

#■勉強に利用させていただいた動画
大変勉強になりました。投稿者様に感謝です。
本ページはこちらを参考に手でやった記録になります。

https://www.youtube.com/watch?v=IyEcu9e1YgM&t=187s

#１．環境構築
自分はWindows環境で構築。

https://prog-8.com/docs/rails-env-win

ruby・コマンドプロンプト・vscodeはあらかじめ入っていたため、
「SQLite」をインストールします。

ちなみに以下すべての記載で入力しているコマンドは、VScode経由での入力です。

####1.1 SQlite
https://sqlite.org/index.html

####1.2 Railsのインストール
そもそも「gem」が何かが不明でしたが以下のページで説明されており、
rubyのパッケージ管理ツールのコマンドのようです。
linuxでいうところのyumのような存在でしょうか。

```
gem install rails -v "5.2.3"
```

https://techacademy.jp/magazine/21213

####1.3 パッケージ管理ツールのインストール

```
gem install bundler
```

Gemfileというファイルを作るためのコマンドを実行。
この時点でこのファイルの意義はまだ未理解です･･･

```
bundle init
```

このコマンドの後、Gemfileというファイルが実行フォルダの直下に作成されるので、
このファイルをテキストエディタで開き、以下を追記します。

```
gem "rails"
```

#1.4.Railsのソースコードインストール
一つ上の手順でGemfileに"rails"という文字と定義したことで、
以下でrailsのソースコードがインストールできます。

```

bundle install --path vendor/bundle
```

#2.Railsでアプリケーション作成
以下のコマンドでRailsのアプリケーションの基礎を作成します。

途中でオーバーライドするかと質問されたら、「A」を押して、オーバーライドします。

```
 rails new .
```

####2.1Railsサーバー起動

```
rails s
```


http://localhost:3000/
Yay! You’re on Rails!
と表示されます。


<details><summary>ここまでのはまりポイント。すんなり、"rails s"ができた人はこの項目は飛ばしてください。
</summary>
<div>

→rails s実行で返ってきた結果を抜粋。
サーバーが起動したとは思えないメッセージです。

>rails\rails_tutorial> rails s
Usage:
  rails new APP_PATH [options]...

同じ経験をされていた方の記事を発見し、こちらで対応してみました。
gitを入れていないことが原因のようです。
https://qiita.com/Leone/items/dc7f8ef2d5329d297e72

gitをインストールvscodeを閉じて開きなおして、再度以下のコマンドでアプリケーションの作成を行いました。

```
 rails new .
```

一回目のgitなしのアプリケーション作成と比べ、かなりファイルが増えました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/736131/cda7808b-3361-eb1c-0eee-103eded975cc.png)


しかしまだ"rails s"コマンドは動きません。
>bin/rails:3:in `require_relative': cannot load such file -- C:/Users/****/Desktop/rails/rails_tutorial/config/boot (LoadError)
        from bin/rails:3:in `<main>'

これは調べてみたら、インストールしていたRubyのバージョンが原因で、boot.rbファイルが作られておりませんでした。
私の環境のRubyは以下のバージョンでした。
>ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x64-mingw32]

以下のダウンロードページから、再度2.7台のRubyを入れなおしました。

https://rubyinstaller.org/downloads/
ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x64-mingw32]
</div></details>

####2.2Railsサーバー停止
ターミナルをctrl+cで閉じるとサーバーが停止され、このページに接続できなくなります。

#3.TOPページ作成

Railsはファイルの命名規則が非常に厳しく、
コントローラーのファイル名「top_controller.rb」とした場合、
クラス名は必ず「TopController」にしないとエラーとなります。

例）ファイル名：小文字アンダーバーで繋ぐ
　　クラス名：ファイル名のアンダーバーを消す。
　　　　　　　「最初の文字」と「アンダーバーの後のアルファベット」を大文字にする。


####3.1 ルーティング設定
ルーティング設定とは、URLをサーバーが受け取ったときにコントローラーどういう処理をさせるかという意味らしいです。
(コントローラーというのはMVCモデルの中のコントローラーを指します)

https://railsguides.jp/routing.html

>Railsのルーターは受け取ったURLを認識し、適切なコントローラ内アクションやRackアプリケーションに割り当てます。ルーターは、ビューでこれらのパスやURLを直接ハードコードすることを避けるためにパスやURLを生成することもできます。

これまでのディレクトリの中に、「config」フォルダがあり、その中のrouter.rbを開きます。
このファイルのdoとendの間に以下を追記します。

```
get '/', to: 'top#index'
```

これの意味としては。
1要素目：getはHTTPメソッドの「get」
2要素目：トップページということで「/」
3要素目：コントローラーとアクションを定義する。この書き方だとTOPコントローラーのindexアクションとなる。

####3.2 コントローラー設定

これまでのディレクトリの中に、「app」→「controller」がありので、そこにファイルを作ります。
作るファイルは「top_controller.rb」とします。

内容は以下の通りにします。
この「ActionController:Base」を継承しているのはコントローラーのルールのようで、絶対に書かないといけないもののようです。

```
class TopController < ActionController::Base
    def index
    end
end
```

####3.3 ビュー設定
これまでのディレクトリの中に、「app」→「views」がありので、そこにフォルダを作ります。
作成するフォルダ名は、コントローラーを「TopController」というクラスで定義したため、「top」となるようです。

topの下にファイルを作ります。
ファイル名は、先のコントローラー設定の中のdefで「index」の名前で定義したため、
index.html.erb
とします。
erbという拡張子を始めた見ましたが、railsでは拡張子を「html.erb」とするようです。

index.html.erbの中身自体は何でもよいので、動画を参考にこんな感じにしました。

```
<h1>Hello world</h1>
```

<details><summary>現状でき上ったものまとめ</summary>
<div>
config\routes.rb

```
Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  get '/', to: 'top#index'
end

```

app\controllers\top_controller.rb

```
class TopController < ActionController::Base
    def index
    end
end
```

app\views\top\index.html.erb

```
<h1>Hello world</h1>
```
</div>
</details>

サーバーを起動してどう動くか見てみます。

```
rails s
```

http://localhost:3000/にアクセスすると、
Hello world
が表示されました。

<details><summary>ただ初回実行時のエラーにありました。</summary>
<div>
以下のエラーが発生しました。
>raise LoadError, "Unable to autoload constant 

コントローラーが読み込めないというエラーのようです。
しかしファイル名の違いなどは何度確認してもなく困惑しました。

改善した方法としては、
top_controller.rbにおいて「ActionController::Base」の箇所を
「ApplicationController」に変えたところ改善しました。
この二つの差異が今のところ不明です。

ただ試した限り、以下の動作後にいずれのパターンでも動作し、原因は不明のままです。
１．ApplicationControllerに変更
２．Hello world表示可能
３．rails停止
４．ActionController::Base：切り替え
５．rails起動
６．Hello world表示
</div>
</details>

#4.DB接続
config\database.ymlが設定に使用するファイルとなるが、現時点での変更は不要です。



####4.1 modelファイル作成
下記のコマンドを実行することでmodelが、app\models\user.rbとして作成する。
意味としては、 rails g model 以降が「DB名」 「列名：データ型」になる

```
rails g model User name:string age:integer
```

以下のようなファイルが作成されました。
invoke  active_record
create    db/migrate/20210302043737_create_users.rb
create    app/models/user.rb
invoke    test_unit
create      test/models/user_test.rb
create      test/fixtures/users.yml


####4.2 DB作成

```
rails db:create
```

####4.3 ユーザーテーブルの作成

4.1で作成した中のmigrateファイル内のデータを使ってテーブルが作成されます。
migrateファイルというのはDBの定義が書いてあるファイルと覚えればよいです。

```
rails db:migrate
```

####4.4 データベースへの接続
今回sqlite3を用いているため、以下のコマンドで接続する。

```
sqlite3 db/development.sqlite3
```

中身を見るにはこのコマンド。

```
.schema users
```

ただ、「rails g model User name:string age:integer」というコマンドでつくったので、userが正しいと思っていたが、
db/migrate/20210302043737_create_users.rbファイル内のcreate文を見ると確かに、
  「create_table "users」の記載があり、この辺りはまだ理解が及びません。。

#### 4.5データの挿入

まずrailsのコンソールを以下のコマンドで立ち上げます。
rails環境でrubyを使用できる環境となる。

```
rails c
```

・insert文

```
User.create!(name:"Aさん",age:19)

User.create!(name:"Bさん",age:20)
```

・select文
このコマンドは内部的には「SELECT  "users".* FROM "users" LIMIT ?」と同じになるようです。

```
User.all
```

・select結果の変数格納
この場合、id:1ののユーザーに対するwhere文となり、その結果が変数格納されます。
「SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  」

```
user=User.find(1)
```

この状態で変数「user」にはid1のユーザーの情報が格納されます。
変数.nameとして名前を見ることや、変数.ageとして年齢を見ることができます。
またそれを指定して内容を更新することができます。

```
user.name="改名A"
```

・update文        
現在、変数userの内容を更新していて、id1のユーザーの名前が"改名A"となっています。
ただこの時点では変数しか書き換えていないため、以下のコマンドでDBに反映させます。
内部的には「UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ?」になっているようです。

```
user.save
```

・select+where文
条件付きのselect文には、下記のコマンドがあります。
User.where(条件)

ageを条件とする場合は、以下となります。

```
User.where("age>=19")
```

#5 新しいページの追加
新しいページを追加します。
今回の目的はユーザーの情報をDBから取得し、画面に出力させます。

流れは、「ルーティングの追記」⇒「コントローラーの追加」⇒「ビュー追加」となります。

#### 5.1ルーティングファイルの更新
例により最初にルーティングのファイルを書き換えます。
「config」フォルダのrouter.rbを開きます。

それぞれの意味として、
「/users/:id」は、users/1やusers/2として、変数で受け取れるようになります。
「to: 'users#show'」は、usersコントローラーのshowメソッドを追加しています。
「as:"user"」はルーティングに対して、名前を付ける機能です。後でユーザー一覧作成の際に使用します。

```
  get '/users/:id', to: 'users#show', as: "user"
```

#### 5.2コントローラーファイルの追加
「app」→「controller」があるので、そこに新しいファイルを作ります。
作るファイルは「users_controller.rb」とします。
内容はTOPページと同じ要領で、
１）ファイル名の大文字＆アンダーバー削除
２）メソッドはルーティングで追加した「show」を入れる。

ここから新しい要素で、 @user=user.find(params["id"])があります。
これは
user.find()は、モデルからデータを抜き出す処理
params["id"]は、ルーティングから受け取るID
最後の変数に結果を格納しています。これに「@」がついているのは、ビューにファイルを渡せるようにするため。

```
class UsersController < ActionController::Base
    def show
        @user=user.find(params["id"])
    end
end
```

#### 5.3ビューファイルの追加
「app」→「views」がありので、そこに新しいフォルダを作ります。
作成するフォルダ名は、コントローラーを「UsersController」というクラスで定義したため、「users」となるようです。

「users」フォルダの配下に、show.html.erbを作成します。
(メソッド名＋html.erb)

ファイルの内容は以下です。
この<%～～～ %>タグの中がRubyのコードを書く領域になります。

<%=と<%の違いは以下の通りです。
<%=：画面表示あり
<%：画面表示なし

if文を書く時には、画面表示しないrubyを使いたいので、そういうときは<%を使うように使い分けができる。

```
<h1>ユーザー詳細</h1>

<%= @user.name %> <br>
<%= @user.age %> 才

```

再び「rails s」でサーバーを起動させ、以下URLにアクセスします。
http://localhost:3000/users/1

画面上で以下の結果が出力されました。
ユーザー詳細
改名A
19 才

####5.4ユーザー一覧を作成する。

同じ流れで、「ルーティングの追記」⇒「コントローラーの追加」⇒「ビュー追加」となります。
「config」フォルダのrouter.rbに以下を追記。

```
  get '/users', to: 'users#index'
```

「app」→「controller」の「users_controller.rb」に追加します。
User.allはすべてのユーザーを取得するコマンドでした。

```
    def index
        @users=User.all
    end
```

「users」フォルダの配下に、index.html.erbを作成します。
(メソッド名＋html.erb)

@usersを受け取って、eachで回しています。
2行目のlink_toはhtmlでいう<a>タグにあたる内容です。
user_path(id: user.id)は、<a>タグ内のhrefにあたり、id:user.idへのリンクを自動生成します。
(まだしっかり理解できていません...)

```
<h1>ユーザーすべて</h1>

<% @users.each do|user| %> 
    <%= link_to user.name,user_path(id: user.id) %> <br>
<% end %>
```

この状態でいかにアクセスすると
http://localhost:3000/users/

画面上以下が表示されました。

ユーザーすべて
改名A
Aさん
Bさん
Bさん

ソースコードは以下のようになっていました。

```
    <a href="/users/1">改名A</a> <br>
    <a href="/users/2">Aさん</a> <br>
    <a href="/users/3">Bさん</a> <br>
    <a href="/users/4">Bさん</a> <br>
```

####5.5 追加機能で、「戻る」ボタンを作ってみます。
ユーザーの詳細画面からへのボタン追加のため、ルーティング設定を行います。
行う設定はas名前の追加です。

「config」フォルダのrouter.rbを以下に変更。

```
  get '/users', to: 'users#index'
　　⇒  get '/users', to: 'users#index', as: "users"
```

show.html.erb　へ以下を追記。

link_to で<a>タグ化し、asで定義したusersという名前を書くことで、その画面へ遷移することができます。

```
<%= link_to "戻る" ,users_path %>
```

#■また次回に続きます。