> When you choose a language, you’re choosing more than a set of technical trade-offs—you’re choosing a community. - Joshua Bloch
這一章介紹一些常見的Rails疑難雜症問題,以及常用的RubyGem套件。更多熱門套件可以參考[The Ruby Toolbox](http://ruby-toolbox.com/)和[awesome-ruby](https://github.com/markets/awesome-ruby)。
## Bootstrap
[Bootstrap](http://getbootstrap.com/)是目前最流行的前端設計框架,讓開發者也可以很輕鬆的進行網頁排版,也很有多現成的Theme可以套用。要在Rails使用Bootstrap,請安裝[bootstrap-sass](https://github.com/twbs/bootstrap-sass)
如果搭配分頁套件kaminari的話,執行rails generate kaminari:views bootstrap3就會產生對應的kaminari樣板。
進一步可以參考[Integrating Rails and Bootstrap](http://www.gotealeaf.com/blog/integrating-rails-and-bootstrap-part-1/)這一系列文章。
## Rake
[Rake](https://github.com/ruby/rake) 用來編寫任務腳本,讓我們在CLI中可以執行。它的好處在於提供良好的任務編寫結構,並且很方便設定各個任務的相依性,例如執行任務C前,需要先執行任務A、B。在 Rails 之中就內建了許多 rake 指令,除了你已經使用過的 rake db:migrate 之外,你可以輸入 rake -T 看到所有的 rake 指令。
而要在 Rails 環境中撰寫 Rake,請將附檔名為 .rake 的檔案放在 lib/tasks 目錄下即可,例如:
~~~
# /lib/tasks/dev.rake
namespace :dev do
desc "Rebuild system"
task :rebuild => ["db:drop", "db:setup", :fake]
task :fake => :environment do
puts "Create fake data for development"
u = User.new( :login => "root", :password => "password", :email => "root@example.com", :name => "管理員")
u.save!
end
end
~~~
透過執行 rake dev:rebuild,就會砍掉重建資料庫,最後執行 rake dev:setup 建立一些假資料作為開發之用。
其他常見的使用情境包括:1\. 修正上線的資料,這樣部署到Production後,可以用來執行 2\. 建立開發用的假資料 3\. 搭配排成工具使用,例如每天凌晨三點寄出通知信、每週一產生報表等等
更多介紹可以參考 [http://jasonseifer.com/2010/04/06/rake-tutorial](http://jasonseifer.com/2010/04/06/rake-tutorial) 這篇文章。
## 分頁
* [will_paginate](https://github.com/mislav/will_paginate)
* [kaminari](https://github.com/amatsuda/kaminari)
## 檔案上傳
* [Paperclip](http://github.com/thoughtbot/paperclip) 是目前使用上最為方便的檔案上傳 plugin。
* [CarrierWave](https://github.com/jnicklas/carrierwave)
## ActiveReord增強
加強搜尋
* [Ransack](https://github.com/activerecord-hackery/ransack)可以很快的針對ActiveRecord做出排序和複雜的條件搜尋。
列表結構(自訂排列順序),搭配 jQuery UI Sortable 就可以做出拖拉排序,可以參考[Sortable Lists](http://railscasts.com/episodes/147-sortable-lists-revised)這篇文章。
* [ActsAsList](https://github.com/swanandp/acts_as_list)
* [ranked-model](https://github.com/mixonic/ranked-model)
樹狀結構
* [ActsAsTree](https://github.com/amerine/acts_as_tree)
* [ancestry](https://github.com/stefankroes/ancestry)
* [awesome_nested_set](https://github.com/collectiveidea/awesome_nested_set)
Tagging 標籤
* [acts-as-taggable-on](https://github.com/mbleigh/acts-as-taggable-on) 製作 Tag 功能。
Soft Deletion 和版本控制,編輯和刪除後還可以留下紀錄和還原,
* [paper_trail](https://github.com/airblade/paper_trail) 另開一個 versions table 完整紀錄
* [paranoia](http://www.rubydoc.info/gems/paranoia) 加一個欄位標記被刪除
有限狀態機,適合用來設計比較複雜的 model 流程狀態
* [aasm](http://github.com/rubyist/aasm)
資料表註解,會幫你在model code上面註解加上所有資料表的欄位
* [annotate_models](https://github.com/ctran/annotate_models)
根據ActiveRecord的關聯自動產生漂亮的Entity-Relationship Diagrams
* [rails-erd](https://github.com/voormedia/rails-erd)
## 處理 HTTP
請參考 [HTTP client](http://ihower.tw/blog/archives/2941) 這篇文章。推薦 [httpclient](https://github.com/nahi/httpclient) 或 [faraday](https://github.com/lostisland/faraday)。
## PDF
* [Prawn](http://github.com/sandal/prawn) 可以產生 PDF,支援 Unicode。
* [PDFKit](http://thinkrelevance.com/blog/2010/06/15/rethinking-pdf-creation-in-ruby.html) 則是另一個有趣的產生方式,透過 HTML/CSS 轉 PDF。
* [Prince](http://www.princexml.com/) 是一套商用方案,將 HTML/CSS 轉 PDF
## CSV
Ruby就有內建這個函式庫了,只需要`require "csv"`即可使用。
## YAML
Rails 的資料庫設定檔 database.yml 是用一種叫 : [YAML Ain’t Markup Language](http://www.yaml.org/) 的格式所撰寫,檔案打開來,看起來就像一般的 plain 設定檔,非常容易修改。
YAML 的設計首要目標就是要讓使用者容易看懂,可以和 script 語言搭配良好。用途有 資料序列化 data serialization、設定檔 configuration settings、log files、Internet messaging、filtering 等。網站上已知有支援的 script 語言有 Python,Ruby,Java,PHP,Perl,Javascript 等。
~~~
require ‘yaml’
ps2 = YAML.load_file(‘example.yaml’)
ps2.each do |it|
puts it.inspect
end
~~~
## JSON
Rails 內建就有 [ActiveSupport JSON](http://caboo.se/doc/classes/ActiveSupport/JSON.html),用法如下:
~~~
ActiveSupport::JSON.encode( [ {:a => 1 , :b => 2 } , "c", "d" ] )
=> "[{\"a\":1,\"b\":2},\"c\",\"d\"]"
ActiveSupport::JSON.decode( "[{\"a\":1,\"b\":2},\"c\",\"d\"]" )
=> [{"a"=>1, "b"=>2}, "c", "d"]
~~~
[yajl-ruby](http://github.com/brianmario/yajl-ruby) 則是一套底層用C,比較快很多的 JSON parser,建議可以讓Rails底層改用這套函式庫,請在`Gemfile`檔案中加入
~~~
gem 'yajl-ruby', :require => 'yajl'
~~~
## XML
Rails 內建使用 Ruby 的 XML 函式庫 [Builder](http://builder.rubyforge.org/)
[Nokogiri](http://github.com/tenderlove/nokogiri) 是一套基於 [libxml2](http://xmlsoft.org/) 的函式庫,效能較佳。可參考 [Getting Started with Nokogiri](http://www.engineyard.com/blog/2010/getting-started-with-nokogiri/)一文介紹用法。
如果要替換 Rails 內建的 XML 函式庫,請在`Gemfile`檔案中加入
~~~
gem 'nokogiri'
~~~
> 有些函式庫為了執行效率,底層會改用 C 的函式庫,適合於正式上線環境,缺點是需要編譯,在一些特殊環境可能無法運作,例如最新版的 Nokogiri 就不支援 Windows 了。而純 Ruby 實作的版本就沒有這個問題。
## 表單
除了用Rails內建的表單Helper,也有一些提供表單設計更方便的套件:
* [simple_form](https://github.com/plataformatec/simple_form)
* [formtastic](https://github.com/justinfrench/formtastic)
## Admin 介面
* [ActiveAdmin](http://activeadmin.info/)
* [RailsAdmin](https://github.com/sferik/rails_admin)
## 如何畫圖表
使用 [GoogleCharts](http://googlecharts.rubyforge.org/) 是最簡單的方式。 如果您使用 jQuery,[flot](http://code.google.com/p/flot/) 是一套不錯的圖表工具。
## Recapache
* [Recaptcha](http://github.com/ambethia/recaptcha) 是做 captcha 最簡單快速的方式。
## 排程工具
如果您有週期性的任務需要執行,除了可以透過Linux的crontab設定去執行rake腳本。例如輸入crontab -e加入:
~~~
0 2 * * * cd /home/your_project/current/ && RAILS_ENV=production /usr/local/bin/rake cron:daily
~~~
就是每天凌晨兩點執行rake cron:daily這個任務。
或是你可以安裝[whenever](https://github.com/javan/whenever)這個 gem,就可以用Ruby的語法來定義週期性的任務,可以很方便的設定伺服器上的cron排程。
## 自動備份
* [https://github.com/meskyanichi/backup](https://github.com/meskyanichi/backup)
可以搭配 whenever 就可以定期備份了
## 升級Rails
小版號的升級,通常透過以下步驟即可完成:
* 修改`Gemfile`的Rails版本: `gem 'rails', '3.1.1'`
* 執行`bundle update`
* 執行`rake rails:update` 會嘗試更新Rails自己產生的檔案,例如config/boot.rb,請一一手動檢查。
升級前,也請參閱官方公告的升級注意事項。
## 如何變更 ActiveRecord 預設的資料表和主鍵名稱
如果要將Rails沿用上舊有的資料庫上,就會發生的資料表名稱和主鍵名稱不是 Rails 預設慣例的情況,也就是表格名稱不是Model名稱的複數型,主鍵不叫id。這時候我們可以手動設定過,例如以下 Model 預設的資料表和主鍵是legacy_comments和id,但是我們想要改成comment和comment_id:
~~~
class LegacyComment < ActeveRecord::Base
self.table_name = :comment
self.primary_key = :comment_id
end
~~~
## 其他
* [http://asciicasts.com/episodes/255-undo-with-papertrail](http://asciicasts.com/episodes/255-undo-with-papertrail)
* [http://intridea.com/2011/5/13/rails3-gems](http://intridea.com/2011/5/13/rails3-gems)
* [http://erik.debill.org/2011/12/04/rake-for-rails-developers](http://erik.debill.org/2011/12/04/rake-for-rails-developers)