Ruby on Rails　MVCの連携

動作環境はMacです。

##Ruby on Railsとは？##

webアプリケーションを作るためのwebアプリケーションフレームワーク。
フレームワークとは、開発者が１から用意しなくても、必要なライブラリや、機能を自動で用意してくれるもの。

Rubyで書かれており、オープンソース（誰でも使用可能）

Railsと呼ばれたりR on Rと略されて呼ばれることもある。

作者　デイビット・ハイネマイヤー・ハンソン氏

**歴史**

2004年7月に最初のバージョンがリリース。

RailsのコンセプトはPHPフレームワークのcakePHPやSymfonyになどに影響を与えている。

**Ruby Gems**

- gemというライブラリの形式が採用。
- よく使う機能がgemで公開されているので、開発工数を削減できる。
- RubyGemsはライブラリの作成やインストールを助けるシステム。

##Railsプロジェクトの作成##

ターミナル

```
$ cd ~/フォルダ名/　#任意のフォルダへ移動
$ cd rails_projects 　#ここではrails_projectsというフォルダを作成し移動
$ rails _5.2.2_new hello　#rails projectsの新規作成コマンド　ここではバージョンを指定している
```

rails newコマンドでアプリケーション作成に必要なフォルダを自動的に生成してくれる。

---

**動作確認**

下記コマンドでrailsの動作確認が可能

```
$rails s #railsサーバーの立ち上げ
```

railsはwebサーバーを持っており、web上で閲覧が可能になる。
rails sを起動し、割り当てられらURLにアクセスすると、welcome画面が表示される。
URLを知っていれば第三者から閲覧が可能になる。


```
$rails c　#railsサーバーの終了
```
上記コマンドでURLにアクセスしてもwelcome画面が表示されなくなる。

**コントローラーの作成**

ブラウザに表示するには、最低でもコントローラーが必要になる。

```
$ rails g controller users index
```

rails g controllerで必要なコントローラーのファイル群を作成。
コントローラー名は複数形が基本。(データベースに紐づかない場合は単数形になる場合も)
indexはコントローラーに記述されるアクション(メソッド)。

```users_controller.rb

class UsersController < ApplicationController #Userscontrollerはappricationコントローラーを継承している。
  def index　#これがアクション（メソッドと同義)
    render plain: "Hello!,World!" #renderはブラウザに表示　plainは平語のテキストの意味
  end
end

```


これでブラウザ上に表示されるようになる。

**ルーティング**

URLとマッチするアクションに振り分けるための機能

下記コマンドでURLとコントローラー、アクションの結びつきを確認することが可能。

```
$rails routes
                   Prefix Verb URI Pattern                                                                              Controller#Action
              users_index GET  /users/index(.:format)                                                                   users#index
       rails_service_blob GET  /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
rails_blob_representation GET  /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
       rails_disk_service GET  /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
update_rails_disk_service PUT  /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
     rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create
```

prefixはパスの指定で使用可能。
VerbはHTTPメソッドのこと。GETはデータ取得　POSTはデータ送信　DELETEはデータ削除など。
URI Pattern はざっくりURLと同義。
Controller#Actionはコントーラーのどのアクションと結びついているかを示すもの


現在下記の通りURLにusers/indexが指定された時にコントローラーのindexアクションが呼ばれる仕様になっている。

```routes.rb

Rails.application.routes.draw do
   #get 'users/index'
    get 'users/index', to: "users#index" #上の記述と同じ意味。
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
```

これをusers/のURLが指定された時にindexアクションがよばれるように書き換えてみる。

```routes.rb

Rails.application.routes.draw do
  #get 'users/index'
  get 'users/', to: "users#index"  #users/indexからusers/に書き換え

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
```

上記に書き換えるとusers/のURL指定でUsersコントローラーのindexアクションが呼ばれる。users/indexに指定すると、Routing Errorrとなる。

routesで確認してみる。

```
rails routes
                   Prefix Verb URI Pattern                                                                              Controller#Action
                    users GET  /users(.:format)                                                                         users#index 
       rails_service_blob GET  /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
rails_blob_representation GET  /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
       rails_disk_service GET  /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
update_rails_disk_service PUT  /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
     rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create
```

**viewの作成**

現在、コントローラーのみをしようして、画面にレンダリング（描写）しているが、RailsのMVC思想に基づくと不自然なので、viewを作成しそこに記述を指定していく。

```users.controller.rb


class UsersController < ApplicationController
  def index
    #render plain: "Hello!,World!"
  end
end

```

上のコントローラのindexアクションにひもづくviewはrails gコマンドの時に自動的に作成されているので、開発者が指定する必要はない。
app/views/controller/index.htmlに記述する
app/views/コントローラー名/アクション名.html.erb

自動的に生成されている。

```index.html.erb
<p> Hello! World.</p>
```

このファイルへの記述でUsersコントローラーのindexアクションと紐付くviewがレンダリングされる。

**ERB**

viewにrubyの機能を埋め込む技術

```index.html.erb
<p> Hello! World.</p>
<p>
  <%= 10 + 1 %> #<%= %>の内側がrubyのプログラム
</p>

```

<%= %>はレンダリングをしたい時の記述
<% %>とイコールを外すと、レンダリングされない
if文など表示する必要がない場合は=は外す。


**ControllerからViewに値を渡す**

Viewへの記述はなるべくレンダリング作業のみにしたいので、プログラミムの処理などはControllerやModelなどに記述するようにする。

```users_controller.rb

class UsersController < ApplicationController
  def index
    #render plain: "Hello!,World!"
  @num = 10 + 1 #viewのプログラムをControllerに記述
  end
end
```

```index.html.erb
<p> Hello! World.</p>
<p>
  <%= 10 + 1 %>
</p>

<p>
  <%= @num %>　#viewへは渡されたインスタンス変数を記述
</p>
```

ローカル変数numとした場合はviewへの描写はできないので注意。

**Modelの作成**

**コマンド**

```
$rails g model モデル名 カラム名:データ型
```

*主なデータ型*
integer 整数
float 小数点
string 文字列
text 長い文字列
boolean 真偽値

どのデータベース製品でも適用できる。

userモデルを作成

```
$ rails g model user name:string age:integer
```

上記コマンドで必要なファイル群が作成される。

/db/migrateフォルダの中に、migrateファイルが作成されている。
これは、テーブルの構造の変更をする際に必要なファイル。

```timestamp_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :name
      t.integer :age

      t.timestamps #自動で作成される。レコードの作成や、編集の日付を管理するカラム
    end
  end
end
```

ターミナルで下記のコマンドを実行しmigrateを実行

```
rails db:migrate
== 20190306031934 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0020s
== 20190306031934 CreateUsers: migrated (0.0021s) =====================
```

**データベース構造の確認**


下記コマンドでデータベースをコマンドで確認することができるようになる。

```
$rails dbconsole
```

```
sqlite> .tables　#テーブルを確認
ar_internal_metadata  schema_migrations     users               
sqlite> .schema users　#usersテーブルの中身の確認
CREATE TABLE IF NOT EXISTS "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "age" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL);　#migrateファイルに記述したtimestampがcreated_atと  updated_atのカラムを自動的に生成してくれている。
```

標準ではsqliteと呼ばれる軽量のデータを扱う製品が用意されている。mysqlなどの他のデータベース製品をしようすることもできる。

.quitか.qで抜ける。

**データベースの操作**


下記のコマンドでデータベースの操作をすることが可能
rubyでいうirbみたいなもの。

```
$rails c #consoleの略
```

```irb

irb(main):002:0> User.all  #Userテーブルのデータを取得
  User Load (0.7ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):003:0> user = User.new　#Userクラスのインスタンスを作成
=> #<User id: nil, name: nil, age: nil, created_at: nil, updated_at: nil>
irb(main):004:0> user.name = "Kiyosiro Imawano"　#インスタンスに名前を代入
=> "Kiyosiro Imawano"
irb(main):005:0> user.age = 40　#インスタンスに年齢を代入
=> 40
irb(main):006:0> user.save　#テーブルにデータを保存
   (0.1ms)  begin transaction
  User Create (0.6ms)  INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Kiyosiro Imawano"], ["age", 40], ["created_at", "2019-03-06 03:58:57.264789"], ["updated_at", "2019-03-06 03:58:57.264789"]]
   (7.0ms)  commit transaction
=> true
irb(main):007:0> User.all　#Userテーブルのデータを取得
  User Load (0.2ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Kiyosiro Imawano", age: 40, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 03:58:57">]>
```

IDのデータを取得

```irb

irb(main):013:0> User.find(1)
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Kiyosiro Imawano", age: 40, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 03:58:57">
```

データの更新　
IDが１のデータを書き換える。

```irb
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Kiyosiro Imawano", age: 40, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 03:58:57">
irb(main):020:0> user.name = "Kensiro Kaneko"
=> "Kensiro Kaneko"
irb(main):021:0> user.age = 23
=> 23
irb(main):022:0> user.save
   (0.1ms)  begin transaction
  User Update (0.5ms)  UPDATE "users" SET "name" = ?, "age" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["name", "Kensiro Kaneko"], ["age", 23], ["updated_at", "2019-03-06 04:11:34.304540"], ["id", 1]]
   (6.8ms)  commit transaction
=> true
irb(main):023:0> User.all
  User Load (0.2ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Kensiro Kaneko", age: 23, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 04:11:34">, #<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">]>

#書き換わった！！

```

Userテーブルのデータを削除

```irb


irb(main):030:0> User.all             
  User Load (5.3ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">]>
irb(main):031:0> user = User.find(2) 
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
=> #<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">
irb(main):032:0> user.destroy　
   (0.6ms)  begin transaction
  User Destroy (0.4ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 2]]
   (1.0ms)  commit transaction
=> #<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">
irb(main):033:0> User.all
  User Load (0.2ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
```

ロードと削除を一緒に行うには
User.find(id).destroyとする。

**Webページにデータを反映させる**

**データベースの作成**

```irb

irb(main):051:0> sato = User.new(name: "Aki Sato", age: 25)
=> #<User id: nil, name: "Aki Sato", age: 25, created_at: nil, updated_at: nil>
irb(main):052:0> sato.save
   (0.1ms)  begin transaction
  User Create (1.0ms)  INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Aki Sato"], ["age", 25], ["created_at", "2019-03-06 12:48:00.277643"], ["updated_at", "2019-03-06 12:48:00.277643"]]
   (6.6ms)  commit transaction
=> true
irb(main):053:0> kaneki = User.new(name: "Ken Kaneki", age: 32)
=> #<User id: nil, name: "Ken Kaneki", age: 32, created_at: nil, updated_at: nil>
irb(main):054:0> kaneki.save
   (0.1ms)  begin transaction
  User Create (1.1ms)  INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Ken Kaneki"], ["age", 32], ["created_at", "2019-03-06 12:48:55.171055"], ["updated_at", "2019-03-06 12:48:55.171055"]]
   (6.5ms)  commit transaction
irb(main):004:0> imawano = User.new(name: "Kiyosiro Imawano", age: 50)
=> #<User id: nil, name: "Kiyosiro Imawano", age: 50, created_at: nil, updated_at: nil>
irb(main):005:0> imawano.save
   (0.1ms)  begin transaction
  User Create (0.8ms)  INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["name", "Kiyosiro Imawano"], ["age", 50], ["created_at", "2019-03-06 12:58:05.599302"], ["updated_at", "2019-03-06 12:58:05.599302"]]
   (6.3ms)  commit transaction
=> true
irb(main):006:0> User.all
  User Load (1.0ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 4, name: "Aki Sato", age: 25, created_at: "2019-03-06 12:48:00", updated_at: "2019-03-06 12:48:00">, #<User id: 5, name: "Ken Kaneki", age: 32, created_at: "2019-03-06 12:48:55", updated_at: "2019-03-06 12:48:55">, #<User
```

```users_controller.rb

class UsersController < ApplicationController
  def index
    #render plain: "Hello!,World!"
  @num = 10 + 1
  @users = User.all #作成したデータをインスタンス変数に代入
  
  end
end
```

```index.html.erb

<p> Hello! World.</p>
<p>
  <%= 10 + 1 %>
</p>

<p>
  <%= @num %>
</p>

<ul>
  <% @users.each do |user| %>
    <li> <%= user.id%>, <%= user.name%>, <%= user.age %> </li>
  <% end %>
#この記述で、ブラウザにデータベースの内容を反映させることができる。
</ul>
```