Rails 下的 form method 技法


#1

首先,你應該先讀完這篇( Ruby下的 ||= , ! , ? , = , == , != )的 getter 與 setter

這邊說的是如何在 model 內進行資料的整理,最簡單的方式應該是獨立一套 getter / setter 而非寫在 callback 做整理

先來一個簡單的範例,假設我們的 User 這個 model 有個生日 birthday 的欄位,欄位值故意是 int,然後我們要讓使用者輸入字串來做修改,方便作法會類似以下

class User
  def form_birthday
    self.birthday ? Time.at(self.birthday).strftime('%Y/%m/%d') : nil
  end
  def form_birthday=(source)
    self.birthday = Time.parse(source).to_i rescue nil
  end
end

然後記得開controller的params的filter,增加:form_birthday,不然會接不到值

之後就可以form的地方用類似的語法

<%= f.text_field :form_birthday %>

再來一個進階的demo,假設 Post 這個 model 有個 column 名為 raw_html,型別為 text,內容強制規定需要 bbcode 轉換才能進來,則可以寫類似以下

class Post
  def form_bbcode=(bbcode_html)
    self.raw_html = BBCode.decode(bbcode_html)
  end
  def form_bbcode
    BBCode.encode(self.raw_html)
  end
end

一樣記得 controller 下的 params 過濾處要加上 :form_bbcode
之後就可以在form的地方用類似的語法

<%= f.text_area :form_bbcode %>

然後就可以很高興的去配上 ckeditor / tinymce 之類的 WYSIWYG 編輯器,然後讓bbcode外掛(model的BBCode要自幹或用別的gem來完成就是)


大概描述一下,form field helper 去顯示 html 的時候,會呼叫該欄位的 form_bbcode(getter) 把值去判別,然後轉成 html ,然而 form 被 client 送出,到Rails後,Rails的 new / create / update_attribute / update_attributes 都會去呼叫 form_bbcode=(setter),所以上面的流程就會變成

使用者送出 => (form_html=) => 經過BBCode轉換成HTML => (raw_html=) #setter
(raw_html) => (form_html) => HTML轉換成BBCode => 使用者編輯 #getter
直接使用raw_html #=> view的顯示

簡單的來說,多建一組或是 N 組 adapter / filter 用的 getter / setter method 就可以防止使用者去修改原值,還可以增加過濾防止錯誤的方式就是,這類的應用非常多,甚至可以做到一個 text 欄位裡面存 Marshal 然後打一票這類的 adapter mathod 餵給 form 還完全不會出錯就是 :smile:

&這篇有問題可以另外問就是,我會另外補上


#2

借題問一下,這個編輯文字要用bbcode 的功用是?編輯器的表單都要用?


#3

BBCode的語法不同於HTML,沒有< > &需要另外編譯就是,類似

所以你可以真對 < > 先做一次 html escape 然後再把 BBCode 的語法翻譯成 HTML 即可,這樣相對安全就是了


#4

你好,我是新新手,請問我希望將使用者輸入的值變成大寫再寫入資料庫,也是用類似這種方法嗎?


#5

可以,不過你也可以加上 callback 完成就是,類似

class User < ActiveRecord::Base
  before_save :check_id_serial_upcase
  private
  def check_id_serial_upcase
    if self.id_serial_changed?
      self.id_serial = self.id_serial.upcase
    end
  end
end 

以上