iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0

框架終於有一點雛形了
相關的 gem 也都安裝完成了
接下來就是做 Controller 啦!

首先,我們先將 version 升成 0.0.2

變更 version

step 1 刪除 rainbow-0.0.1.gem

step 2 git add .

step 3 更改 version 為 0.0.2

module Rainbow
  VERSION = "0.0.2"
end

step 4 重新安裝套件

> gem build rainbow.gemspec

  Successfully built RubyGem
  Name: rainbow
  Version: 0.0.2
  File: rainbow-0.0.2.gem

> gem install rainbow-0.0.2.gem

  Successfully installed rainbow-0.0.2
  Parsing documentation for rainbow-0.0.2
  Installing ri documentation for rainbow-0.0.2
  Done installing documentation for rainbow after 0 seconds
  1 gem installed

step 5 quotation 也要記得更新

> bundle update rainbow

Rainbow 設定 Controller
當請求抵達 web server 及 application server 時

Rack 會把程式碼傳過去,這時候需要知道哪個 Controller 及 action 要處理這個請求

# /rainbow/lib/rainbow.rb
require "rainbow/routing"

module Rainbow
  class Application

    def call(env)
      # Controller 是 class,而 class 為保留字,所以這邊用 klass 代替
      klass, act = get_controller_and_action(env)
      controller = klass.new(env)
      text = controller.send(act)
      [
        200, 
        {'Content-Type' => 'text/html'},
        # 記得這裡要換成 text
        [text]
      ]
    end

    class Controller
      # 初始化載入環境變數
      def initialize(env)
        @env = env 
      end

      def env
        @env
      end 
    end 
  end
end

web小辭典

▶ Rack Env: 一個 hash 物件,裡面含有 HTTP request、rack資訊、其他資訊(ex. WEBRick增加的資料)

▶ PATH_INFO: 以偽靜態頁面方式運作,不包含 query 參數(放置於?後面)的 URL,會告訴 Rails 要用哪個 Controller 跟 action

Rainbow 設定 routing
在 rainbow/lib/rainbow 新增 routing.rb
設置路徑,把路徑拆開拿到 Controller 及 action

# /rainbow/lib/rainbow/routing.rb

module Rainbow
  class Application
    def get_controller_and_action(env)
        
      # 把路徑分成四份,分為 Controller前 / Controller / action /剩下的
      _, cont, action, after = env["PATH_INFO"].split('/', 4)
        
      # 首字轉大寫,剩下轉小寫 ex."Quotes"
      cont = cont.capitalize
        
      # 加上 Controller ex. "QuotesController"
      cont += "Controller"
        
      # const_get 會去尋找大寫開頭的 Controller class
      [Object.const_get(cont), action]
        
    end
  end 
end

在 Quotation 中建立 controller

step 1 設定 Controller 及 action

是不是很像在 Rails 中的 Controller 呢
現在我們要設定 Controller 並加入 action

# /quotation/app/controller/quotes_controller.rb
class QuotesController < Rainbow::Controller
  def a_quote
    "You Only Live Once, " + "hang on to your dreams."
  end
end

我們還沒在 Controller 加入 Rails autoloading
所以在 config/application.rb 中設定 LOAD_PATH 並把 Controller 載入

# quotations/config/application.rb
# 檔案路徑加入 app/controllers 讓 routes 知道要找哪個 Controller 跟 action
$LOAD_PATH << File.join(File.dirname(__FILE__),
"..", "app", "controllers")

require "quotes_controller"

web小辭典

▶ Rails autoloading: 使用 require 載入文件時,Ruby 會去找 $LOAD_PATH 並把對應的檔名找出來,後面會更詳細的介紹

step 2 刪除 rainbow-0.0.2.gem

step 3 git add .

step 4 重新安裝套件

> gem build rainbow.gemspec

  Successfully built RubyGem
  Name: rainbow
  Version: 0.0.2
  File: rainbow-0.0.2.gem
  
> gem install rainbow-0.0.2.gem

  Successfully installed rainbow-0.0.2
  Parsing documentation for rainbow-0.0.2
  Done installing documentation for rainbow after 0 seconds
  1 gem installed

Quotation 終端機啟用 rackup

rackup -p 3001

http://localhost:3001/quotes/a_quote

就會看到quote在畫面上囉

錯誤訊息

回來看終端機,會發現出現了一行錯誤訊息

NameError: wrong constant name Favicon.icoController

瀏覽器會自動讀取favicon.ico
但暫時先用避開的方法處理

# rulers/lib/rulers.rb /module Rainbow

class Application
  def call(env)
    if env['PATH_INFO'] == '/favicon.ico'
      return 
        [
          404,
          {'Content-Type' => 'text/html'}, 
          []
        ]
    end
        
    klass, act = get_controller_and_action(env)
    controller = klass.new(env)
    text = controller.send(act)
    [
      200, 
      {'Content-Type' => 'text/html'},
      [text]
    ] 
  end
end

基本的 routing、Controller、action 建立好囉
我們明天來建立 debug 功能!


上一篇
Day 07 完整框架的基本功能(二)
下一篇
Day 9 - Controller debug
系列文
從0開始刻 淺談 Rails 的運作魔法30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言