Ruby on Rails 網站程式設計基礎班

第四課:網頁程式簡介、Rails 入門

Ubuntu 無法打中文

Ruby 風格指南

心理建設

作業卡關是常態,不要輕易放棄

請花時間練習英文,對你絕對沒有壞處

 

 

 

HTTP 協定

HTTP 協定

1. 資源 (resource) + 方法 (method)

 

2. 無狀態性通訊 (Stateless protocol)

 

 

 

HTTP 的動詞

為了要和伺服器溝通,HTTP 制定了九種動詞,用於支援 CRUD 的操作:
 

- GET        (讀取)

- POST     (新增)

- PATCH  (部分更新)

- PUT       (完全更新)

- DELETE (刪除)

HTTP 的動詞

所以搭配上 url 後,就可以對資料進行操作了:
 

- GET           /users

- POST        /users

- PATCH     /user/1

- PUT          /user/1

- DELETE    /user/1

API

1. Application Programming Interface

    (應用編程介面)

2. 給不同程式互相溝通用的介面

 

 

 

 

Welcome to Ruby on Rails!

About Rails

DHH 開發於 2005 年

MVC 架構

Convention over Configuration (COC)

Don't Repeat Yourself (DRY)

敏捷開發

 

 

 

MVC 架構

應用程式設計架構

最早源自 smalltalk 語言的概念

簡化專案結構、易於分工以及維護

MVC 架構

<?php
  $db = mysql_connect("localhost", "root", "password");
  mysql_query("SET NAMES 'utf8'");
  mysql_select_db($SERVER['db']);
?>
<html>
  <?php
    $sql="select * from news where Class='1' or Class='3' order by CTDate desc limit 0,5";
    $result= mysql_query($sql);
    while ( $arr=mysql_fetch_array($result) ) {
      echo <<<NEWSEND
        <div class="box">
          <span class="box-title-1"> <b>【$arr[Title]】</b> $arr[CTDate] </span>
          <div class="box-content">
            $arr[Text]
          </div>
        </div>
      NEWSEND;
    }
  ?>
</html><?php
  $db = mysql_connect("localhost", "root", "password");
  mysql_query("SET NAMES 'utf8'");
  mysql_select_db($SERVER['db']);
?>
<html>
  <?php
    $sql="select * from news where Class='1' or Class='3' order by CTDate desc limit 0,5";
    $result= mysql_query($sql);
    while ( $arr=mysql_fetch_array($result) ) {
      echo <<<NEWSEND
        <div class="box">
          <span class="box-title-1"> <b>【$arr[Title]】</b> $arr[CTDate] </span>
          <div class="box-content">
            $arr[Text]
          </div>
        </div>
      NEWSEND;
    }
  ?>
</html>

早期包山包海的網頁...

Rails 的 MVC 架構

1. Model 封裝資料與商業邏輯,與資料庫裡的資料表對應

2. View 處理使用者介面,顯示及編輯表單,可內嵌Ruby語法

3. Controller 負責將資料送進送出Model,處理從外界 (也就是瀏覽器) 來的HTTP Request請求,與Model互動後輸出View (也就是HTML)

 

 

 

MVC 雜想

1. 每一個自稱是 MVC framework 對 MVC 的定義不一定一樣,     因為大家都把 MVC 再定義了

2. 最初 Smalltalk 的 MVC 是指 Model 改變後需要以 Obesrver     Pattern 去主動告知 View 去做出對應的更新,但是在 HTTP       的世界裡,我們很難這樣做,而是由 controller 回應給 View

3. 近年越來越流行 frontend javascript framework,後端              framework 變成單純回傳 json / xml 的 API server。                Presentaion layout 和 backend 就變得越來越沒關係了

 

 

How Rails Work

1. 瀏覽器發出HTTP request請求給Rails

2. 路由(Routing)根據規則決定派往哪一個Controller 的 Action

3. 負責處理的 Controller Action 操作 Model 資料

4. Model 存取資料庫或資料處理

5. Controller Action 將得到的資料餵給View樣板

6. 回傳最後的 HTML 成品給瀏覽器

Rails Scaffold

# 使用 scaffold 指令

$rails new dinbento

$git init

$git add .

$git commit -m "first commit"

$rails g scaffold order name:string phone:string description:text

$rake db:migrate

$rails server

我們來看一下 Scaffold 做了十麼

$git diff

routes.rb

Rails.application.routes.draw do
  resources :orders

end

config/routes.rb 是一個 Rails 專案管理路由以及相對應 Controller Action 的檔案,Rails 專案的路由都是在這裡設定

Controller File

class OrdersController < ApplicationController
  before_action :set_order, only: [:show, :edit, :update, :destroy]

  # GET /orders
  # GET /orders.json
  def index
    @orders = Order.all
  end

  # GET /orders/1
  # GET /orders/1.json
  def show
  end

  # GET /orders/new
  def new
    @order = Order.new
  end

  # GET /orders/1/edit
  def edit
  end

  # POST /orders
  # POST /orders.json
  def create
    @order = Order.new(order_params)

    respond_to do |format|
      if @order.save
        format.html { redirect_to @order, notice: 'Order was successfully created.' }
        format.json { render :show, status: :created, location: @order }
      else
        format.html { render :new }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /orders/1
  # PATCH/PUT /orders/1.json
  def update
    respond_to do |format|
      if @order.update(order_params)
        format.html { redirect_to @order, notice: 'Order was successfully updated.' }
        format.json { render :show, status: :ok, location: @order }
      else
        format.html { render :edit }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /orders/1
  # DELETE /orders/1.json
  def destroy
    @order.destroy
    respond_to do |format|
      format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_order
      @order = Order.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def order_params
      params.require(:order).permit(:name, :phone, :description)
    end
end

Controller 主要的功能:

 1. 收集 request 的資訊,例如 使用者傳進來的參數

2. 操作 Model 來做資料的處理

3. 回傳 response 結果

Model File

class Order < ActiveRecord::Base
end

和資料庫的資料表相對應的抽象類別,和其他資料表的關聯、行為、商業邏輯等都是在這裡定義或處理

View File

<p id="notice"><%= notice %></p>

<h1>Listing Orders</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Phone</th>
      <th>Description</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @orders.each do |order| %>
      <tr>
        <td><%= order.name %></td>
        <td><%= order.phone %></td>
        <td><%= order.description %></td>
        <td><%= link_to 'Show', order %></td>
        <td><%= link_to 'Edit', edit_order_path(order) %></td>
        <td><%= link_to 'Destroy', order, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Order', new_order_path %>

Rails Framework & MVC

Controller 層面 - ActionPack::ActionController

View 層面 - ActionPack::ActionView

Model 層面 - ActiveRecord

My First Rails App

$rails new my_app_name

建立新專案

My First Rails App

$bundle install

安裝執行這個專案需要的 gem:

What is bundler?

Gem 依存性(dependencies)管理工具

會根據 Gemfile 的設定自動下載及安裝 Gem 套件

在團隊開發時,維持開發者之間套件版本的一致性

 

Rails 專案裡一些重要的設定檔

config/database.yml

config/routes.rb

Gemfile

 

database.yml

Rails 專案與 database 連結的設定檔

development 是用於開發時的設定

test 是用於執行自動測試時的設定

production 是用於正式環境上的設定

 

 

routes.rb

設定 URL 的檔案

設定一個 Rails 專案的 API (應用程序介面)

 

可以透過以下網址查詢:http://localhost:3000/rails/info/routes

 

也可在 terminal 裡輸入 rake routes 查詢

 

 

Gemfile

宣告在這個 Rails 專案中使用的 gem ( Ruby 套件)

bundler 會依據 gemfile 安裝該專案需要的套件

每次執行 bundle 後會產生 Gemfile.lock

Gemfile.lock 會詳細列出所有 gem 的版本

 

*不要修改 Gemfile.lock

 

 

 

 

MVC 就從 M 開始

Active Record

Ruby 的 ORM (對映射關聯式資料與物件資料)

 

簡單來說,就是把資料表物件化,讓開發者不須使用 SQL 語法,直接用熟悉的 Ruby 於法操作資料

 

更簡單的說,它就是 SQL 語言與 Ruby 語言的翻譯官

Active Record

從物件導向的角度來對映 SQL 資料庫

 

一個資料表對是應到類別 (Class)

資料表的每一筆資料則是對應到物件 (Object)

ActiveRecord CRUD

 

 

CREATE  -  新增資料

READ      -  讀取資料

UPDATE - 編輯資料

DELETE  - 刪除資料

 

# 建立一筆 Order 資料
Order.create(name: "Bob", phone: "88888888888", description: "hamburger")

# 尋找這筆資料
Order.find(1)

# 更新這筆資料
Order.find(1).update(description: "sandwich")

# 刪除這筆資料
Order.find(1).destroy

資料操作方式

對應的 ActiveRecord 方法

Rails Console

類似 irb,不過只屬於一個專案的環境

可在裡面測試 ActiveRecord

 

 

$rails console

或

$rails c

Homework

OOP Rock Paper Scisscors

Quiz 1 & 2

deck

By Eugene Chang