在 Rails3 中,處理 JavaScript 改採用 UJS 的方式,也就是以往 inline JS 的情況將不復見,link_to_remote 跟 remote_form_for 都沒有了:

例如:

link_to 'Logout', session_path, :method => :delete

產生出來的是:

<a href="/session" data-method="delete" rel="nofollow">Logoout</a>


例如

link_to 'Ajax delete', person_path(person),
      :remote => true, :confirm => "Are you sure?"


產生出來的是

<a href="/people/1"  data-confirm="Are you sure?" data-method="delete"
              data-remote="true" rel="nofollow">Ajax delete</a>
# 點下去會向 Server 要求 JavaScript 內容執行

Rails3 預設還是使用 Prototype.js,要換成 jQuery 非常簡單。首先在產生 rails 專案時,可以輸入 rails your_project -J 就不會產生 Prototype.js 的檔案。

修改 /public/javascripts/rails.js 這個檔案,內容換成 http://github.com/rails/jquery-ujs/blob/master/src/rails.js 這個官方提供的 jQuery js driver。

在 Rails layout 的 HTML head 中加入:

<%= csrf_meta_tag %>
<%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" %>
<%= javascript_include_tag 'rails' %>

其中 csrf_mate_tag 產生的是做 CSRF 防禦的 authenticity_token,以往這也是 inline 在 HTML 中,現在則是先宣告在 HTML head 中。

另外要提醒你,如果你有使用 RJS 的話,Rails3 的 RJS 還是只會產生 prototype.js 的版本。所以如果非得用 RJS 的話,目前恐怕還是得裝以往 Rails2 用的 jRails,這好像有點蠢。也許是時候把 RJS 徹底揚棄,直接寫 jQuery 好了(?)

例如上面的 Ajax delete 例子,它的 controller 跟 js 可以這樣:

# people_controller.rb
  def destroy
    @person = Person.find(params[:id])
    @person.destroy

    respond_to do |format|
      format.html { redirect_to(people_url) }
      format.js # destroy.js.erb
    end
  end

# destroy.js.erb
jQuery("#<%= dom_id(@person)%>").remove();

FaceboxRender 是我最近寫的第二個 Ajax UI plugin,它讓你在 Rails 中可以無縫使用 lightbox 效果,搭配使用的 Javascript library 正如其名是 Facebox。首先你得先裝好 jQuery 和 Facebox:

  1. 下載 jQuery (建議你可以考慮用 jRails 完全換掉 Prototype library)
  2. 下載 facebox
  3. 把 facebox js file 放到 /public/javascripts/
  4. 把 facebox css file 放到 /public/styleshees/
  5. 把 facebox all image files 放到 /public/facebox/
  6. 設定好 layout 的 stylesheet_link_tag 和 javascript_include_tag 加入這些 js,css 檔案

facebox-render 目前放在 github,請下載後放到 vender/plugins/facebox_render

然後在你要使用的 Controller 加入以下程式碼

 include FaceboxRender

或是你直接放到 /app/controllers/application.rb 裡面也是可以。

回到 view code,當你要叫出一個 lightbox :

 facebox_link_to "Login", :url => login_url

或是你也可以用 remote_link_to, remote_form_tag 等Rails內建的 Ajax Helper,差別在於 facebox_link_to 會先秀出一個 Loading lightbox,然後再送 Ajax request。

重頭戲是 action :


def new
 # do some thing you want
 respond_to do |format|
  format.html
  format.js { render_to_facebox }
 end
end

這裡巧妙的運用了 respond_to 來處理 ajax request,預設的 render_facebox 會 render 不帶 layout 的HTML(即 new.html.erb)。當然我們也支援傳入 :action, :template, :partial 等常見的Rails參數,或是乾脆傳入 :html 也可以。

傳入 :msg 的話,會插入一段 <div class=”message”>your msg</div> 到裡面去,方便你做一些提示或警告訊息。

除了 render_facebox,也有 close_facebox 可以關掉 lightbox。也可以用 redirect_from_lightbox 重新讀取另一頁。

實際的應用非常方便,你可以在網頁中用 remote link 或是 remote form submit 叫出 facebox。在 facebox 中也還可以再放 remote link 或 remote form submit,接收處理的 action 可用 render_facebox 或關掉 close_facebox 抑或重新讀取頁面 redirect_from_facebox。

FaceboxRender 的隨附文件請見 README

P.S. 這篇文的英文版在 Handlino’s blog

Spakit 源自 registrano.comMassage,是一個可以讓你將現成的網站輕鬆轉換成 SPA (single page application) 的 Rails Plugin。只需在 view 中換用 Spakit helper,不需要更動 controller code,就可將超連結和表單送出變成 Ajax 送出並更新頁面。

spakit 目前放在 github,另外也包成 gem,安裝方式如下:

 gem install spakit
 cd /your_rails_app/vendor/plugin
 gem unpack spakit
 mv spakit-0.9.0 spakit

並且 rename 成 spakit。裝好之後,首先建立一個 Spakit 專用的 Layout,一個簡單的範例如下:

# /view/layouts/spakit.rhtml
<p><%= flash[:notice] %></p>
<%= yield %>

接著就可以使用 Spakit 專用的 helpers,目前有 spakit_link_to, spakit_form_for 和 spakit_form_tag 三種可以使用,用法如下:

spakit_link_to 'new person', :url => new_person_path
spakit_form_for @person, :url => people_path

如此按下連結或送出表單後,Spakit 就會送出 Ajax request(i.e. prototype’s Ajax.Updater ),然後將回傳的 HTML 結果更新到#content 區塊。

如果你想要支援 Ajax 的 Histroy Bookmarks,建議可以採用 Really Simple History(RSH) library 來處理瀏覽器的上一頁下一頁問題,這部份的範例程式附在 plugin 的 README (使用到 jquery library,好心人有空可以幫忙寫 prototype version)。

P.S. 這篇文的英文版在 Handlino’s blog

Next Page »