從 RailsTips: Config So Simple Your Mama Could Use It 這篇看到一個非常簡單漂亮的用法,因為還蠻常
在 Rails 裡面用到的,特此一記:
閱讀全文〈自定 YAML Config 設定檔〉
如何正確發送(大量) Email 信件
Update(2011/5): 推薦 Amazon SES 服務
Update(2010/5): So You’d Like to Send Some Email (Through Code) 也可以一看
Update(2011/7): 推薦 Postmark,也有 Rails plugin。
在眾多客戶需求中,我最害怕的其中一條”順便”要做的功能就是,在後台可以寄信給”全部的”使用者。
寄 “email” 而已,不是非常簡單嗎?
寄給幾個人是很簡單,但是要寄給”一群”人,那就不是件簡單的事情了,在這 spam 肆虐的年頭, 信寄出去不一定就能順利到達使用者的收件夾。
Engine Yard 的這兩篇 How To Ensure Your Email Gets Delivered 和 Making Sure Your Email Gets Delivered 點出了寄 Email 要注意的事項:
- 處理退信
Bonuce mail 是你寄出去的信件,但是因為某些理由(地址不對、對方信箱滿了)而被對方 mail sever 退信,這些 email 你必須要處理。如果你忽略它還一直寄,你就長得蠻像發垃圾信的傢伙,而會被列出黑名單之中。
- 與主要的 Email 服務商設定意見反應機制(Feedback Loop)
Feedback Loop 是一項協助處理當你的 email 被使用者按下 “垃圾信” 的服務。透過主動接觸主要的 Email 服務提供商,去建立用戶意見反應機制。例如 台灣Y!、Yahoo! Complaint Feedback Loop、msn等,減少被寄件者檢舉成垃圾信的次數。
- 建立自已的 email 清單
建立你自己的 mail 清單。如果你的清單是買來的,不但收件人沒有同意要收到你的信件,也會有很高的機會是 bonuce mail。寄出大量的非允許郵件,終究會讓你的 IP 被列出黑名單。
標準的作法是,要在使用者註冊後,且他們也確認收到註冊的認證信(透過email上的認證連結),如此便可以確保這個 email 的正確性,而不會變成 bonuce mail。你也應該避免寄出跟你服務無關的email,減少被檢舉成垃圾信的機會。
- 不要使用 100% 以圖片為主的內容
減少使用圖片,像 Gmail 預設就不會讀取圖片,重要的資訊使用圖片可能會讓使用者預設就看不到。充滿圖片的的 email 也容易判讀成垃圾信。
- 使用垃圾信判讀工作測試
收信的 mail server 通常會使用如 Spam Assassin 的工具來判讀是否是垃圾信,而你也應該用這類的工作檢查你寄出去的信件。www.brandonchecketts.com/emailtest.php 是一個線上的檢查工作,如果你的分數太低,顯然很可能被判讀成 spam。至於為什麼分數低,可以參考這篇文章。
- 驗證 HTML
如果你寄的是 HTML 格式,你應該檢查 HTML 格式是否正確。一封畸形的信件也容易變成 spam。
- 模擬測試終端使用者環境
使用不同 email clients 實際測試,例如 litmusapp.com 這個工具。不同的 client 可能會顯示不同的結果。
- 專屬 IP
是否有專屬的 IP。如果你的 email sever 是跟人共用的,很可能別人被 spam 了,跟著害到你被列入黑名單。
- 設定 SPF Validation
SPF (Sender Policy Framework) 是一項 e-mail 協定來確認 return-path address 的正確性,用以防止垃圾信件。設定 SPF 可以改進你的信件發送成功率,特別是 hotmail(MSN)。
- 設定 Domain Keys Verification
Domain Keys 驗證是另一種防止垃圾信件的協定。
- 設定 Reverse DNS 反查
設定反向查詢的 DNS 記錄,如果你寄信的 IP 無法反查,可能根本就寄不到。
- 驗證寄信者地址
你的寄信人 email 位址也要是正確存在的。許多 email 服務商會先檢查寄件人的地址是正確的,才會收信。
接下來麻煩的是,如果你終究還是不小心被列成黑名單,該怎麼辦? 這篇文章也列出一些常見的原因。
Anyway,我的結論是,還是交給專業的來吧~ 自己架設/管理 email server 不但辛苦又會被 blocked。如果信件量一天低於 500 封,我會建議採用免錢 Gmail 來寄信;超過的話,則有一些第三方服務可以採用,例如 Amazon SES、Sendgrid 或 Authsmtp。 如果需要比較多的行銷功能,則可以考慮 Madmimi、Campaignmonitor 或 Mailchimp 等服務。
BTW,既然提到了 Campaign Monitor,如果你有心做 Email marketing,他們家有不少值得一讀的資源,例如 Guide to CSS support in email clients 就十分有用。
如何有效率地分頁?
Efficient Pagination Using MySQL 是一份針對分頁這件事情如何更快的 PDF。
傳統的分頁方式,正如 will_paginate plugin 所做的:顯示所有頁數跟連結。有個不 scale 的問題是,它用了 OFFSET 跟 COUNT,當資料量越來越多,分頁的速度就會越來越慢 :(
SELECT count(*) FROM messages SELECT * FROM messages ORDER BY id DESC LIMIT 0, 20
這裡提出的解決方案如同 Twitter 所採用的,只讓使用者點下一頁:
不要顯示頁數、不要顯示總數量,可以搭配使用 Ajax 換下一頁。如此就可避免使用到 OFFSET 只用 LIMIT,也減少了一次 COUNT query。
page1 = SELECT * FROM messages LIMIT 10 WHERE id > 0 ASC id page2_min_id = page1.last.id page2 = SELECT * FROM messages LIMIT 10 WHERE id > page2_min_id ASC id
當然,有個缺點就是使用者沒辦法知道總共有多少資料了。
Moneta: 提供 key/value stores 的統一介面
今天我想特別介紹這一套 Ruby library: Moneta
它提供了 key-value stores 標準共通的使用介面,讓你可以用相同的程式,但是可以輕易轉換底層實際使用的儲存庫,包括:
- Basic File Store
- BerkeleyDB
- CouchDB
- DataMapper
- File store for xattr
- In-memory store
- Memcache store
- Redis
- S3
- SDBM
- Tokyo
- Xattrs in a file system
它的用法其實跟 Hash API 差不多,非常容易使用。我認為最實際的用途是用在撰寫快取程式了。
因為不同環境可以輕易切換 store 的這個好處,我在 local 的 development 環境中,可以使用 In-memory store 或 File Store (前者重開 server 快取資料就會消失,後者則會留著),不需要多裝東西就可以寫快取。更重要的是,團隊中其他人也不需要費心設定 (叫每個人都去裝 Memcached 也太辛苦了)。而在 production 正式環境中,則可以輕易設定成使用 Memcached。
我自己也用了 Moneta 介面寫了一個小程式 Headcache,提供了 get_and_set 功能:
data = Handcache.get_and_set("data-123", :expires_in => 60 ) do
"cached-foobar"
end
如果快取存在,就回傳快取資料;如果不存在,就執行 code block,並將最後的運算值回傳並快取起來。
如果是在 View 中搭配 partial 使用也非常簡單:
<%= Handcache.get_and_set( dom_id(@post), :expires_in => 60 ) do
render :partial => "post"
end %>
設定的方法則可以是:
# config/environments/development.rb
begin
# for developer has tokyo cabinet
Handcache = Moneta::Tyrant.new( :host => 'localhost', :port => 1978 )
rescue
# for developer has not tokyo cabinet
Handcache = Moneta::BasicFile.new( :path => "tmp" )
end
關於快取這件事情的學問,可以參考我之前的 Memcached 文章:一是如何清除過期的快取資料(expire),二是注意快取 Key 的命名。
Rails Best Practices Gem: 靜態分析Rails程式碼
Rails Best Practices Gem 是 flyerhzm 根據我的 Rails Best Practices 演講的內容,所作出來的靜態分析程式,可以幫助你快速找到一些可能可以改善的地方。
透過 sudo gem install rails_best_practices –source gemcutter.org 安裝之後,只要執行 rails_best_practices . 就會開始分析你的程式,十分神奇。
這個 gem 也被 Ruby5 – Episode #28、Rails Envy Podcast – Episode 102 和 InfoQ China 等介紹。
RubyConf Taiwan 2010: Call for Papers
RubyConf Taiwan 2010 開始接受投稿了,截止日期為2010年1月31日,有兩種形式的議程可供選擇:
- Session: 45分鐘
- Talk: 20分鐘
投稿方式請詳見公告 RubyConf Taiwan 2010 Call For Papers。