[筆記] ERubies 在 Rails 做的事情

因為小畢在 Slack 上面對 SanitizeHelper 發問,所以就順手找了一下 Erb 在 Rails 中是怎麼處理 render 的(包含 html_safe? 之類的判斷),才發現 ERuby 是一個大 compiler …… 負責把 HTML + embedded ruby compile 成 ruby code,而且其實還有 ERubies 在後面把專案做大,現在有 EC、EPHP、EJava……等 compiler 了。

以下是我在 Slack 上面回小畢的內容節錄,有空再回來整理……(喂

我看 code 之後發現沒加 `sanitize`
用的是 ERB 的 html escape function 而不是 `sanitize`

主要是這裏有一個 Erb compiler
https://github.com/rails/rails/blob/a60e6ddb83b036f9b92af5dbcfda265cd0fde3b2/actionview/lib/action_view/template/handlers/erb.rb
會把 .erb file compile 成 ruby code

然後這邊會根據 compile 出來的 ruby code 塞進去這個 function generator 裡面,
https://github.com/rails/rails/blob/a60e6ddb83b036f9b92af5dbcfda265cd0fde3b2/actionview/lib/action_view/template.rb#L274
所以如果你的 erb file 有錯誤的話會噴一個很奇怪的 function name 是因爲他是這裏產生的

我說的錯誤大概是像這個樣子
```
Rails.root: /home/davy/junk/junk

Application Trace | Framework Trace | Full Trace
app/views/layouts/application.html.erb:11:in `_app_views_layouts_application_html_erb___282794924495449819_38551460'
```

接下來是 `SafeBuffer` 有一個 method 叫做 `safe_append` (alias as `safe_concat`) 會辨識丟進來的是不是 `html_safe?` 如果是就直接塞進 buffer
如果不是,就透過 `ERB::Util.h` (alias as `ERB::Util.html_escape`) 做 escape 之後塞進 buffer

這之間都沒有經過 `SanitizeHelper` 或是它的實作 `Rails::Html::WhiteListSanitizer` (https://github.com/rails/rails-html-sanitizer/blob/master/lib/rails-html-sanitizer.rb)

然後這個實在是太噁心了,簡直,噢不,根本就是在 template 裡面寫了一個 erb to ruby to html compiler ……

所以他不是一個 pipeline 在跑……而是有一個 compiler 在做全部的事情……囧
然後我發現 Eruby (Erb) 本來就是一個 eXX (erb, ephp, ejs, ...) 的 compiler……
負責把 html 跟目標語言的語法混合的檔案 compile 成目標語言程式碼(再執行)
(這邊指的是連單純的輸出也是靠目標語言在輸出,例如 ruby 就是會產生一段 code 在把內容塞到一個叫做 _buf 的 ruby 變數中; PHP 就是直接產生一個 .php 格式的內容(因爲 php 可以直接撰寫 html 做輸出);java 是塞到 StringBuffer 裡面)
https://github.com/guenter/erubis/tree/master/lib/erubis/engine

ERubies 的 target 清單……噁心,太噁心了
http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-php

然後 Rails 有重寫 erb 的一些 method
https://github.com/rails/rails/blob/d94ae72a5259c31ea510e6341bbbf4e920312ebe/activesupport/lib/active_support/core_ext/string/output_safety.rb

因主題更新,留言功能暫時停用中。