首先需要注明一點,本文是原創的並不是從其它地方轉載。所有的數據是我從 GitHub 和 RubyGems 上碼下來的,數據的截取時間就是本文的發布日期。
RubyGems 的下載量可以看到在用這個 gem 的人數,所以數值很大(這里收藏的下載量至少會大於10萬級)。而在 GitHub 上的則代表關注這個gem的源碼的人數(本文收藏的至少是過 1k以上 Star 的 repository)
Nokogiri
gem 'nokogiri'
采集數據是我們需要解析復雜的 HTML 結構,從中獲得需要的數據,Nokogiri 可以幫助我們完美的處理不同網頁上面不同的 HTML 結構,並且有很好的編碼處理能力,用它你不用擔心頁面是 GB2312 還是 GBK 還是 UTF-8,它都很很好的處理,解析結構可以用類似 jQuery 的 CSS Selector 的方式查找,很是方便。曾經用過 Ruby 的好幾個類似插件,最終發現 Nokogiri 才是最好的。
Faraday
gem 'faraday', '~> 0.9.1'
Faraday 是一個HTTP的客戶端,可以提供一般化的接口和多種的適配器 (例如 Net::HTTP)。
做一些網絡服務API集成它是一個很好用的助手。
conn = Faraday.new(:url => 'http://sushi.com') do |faraday|
faraday.request :url_encoded # form-encode POST params
faraday.response :logger # log requests to STDOUT
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
end
## GET ##
response = conn.get '/nigiri/sake.json' # GET http://sushi.com/nigiri/sake.json
response.body
conn.get '/nigiri', { :name => 'Maguro' } # GET http://sushi.com/nigiri?name=Maguro
conn.get do |req| # GET http://sushi.com/search?page=2&limit=100
req.url '/search', :page => 2
req.params['limit'] = 100
end
## POST ##
conn.post '/nigiri', { :name => 'Maguro' } # POST "name=maguro" to http://sushi.com/nigiri
# post payload as JSON instead of "www-form-urlencoded" encoding:
conn.post do |req|
req.url '/nigiri'
req.headers['Content-Type'] = 'application/json'
req.body = '{ "name": "Unagi" }'
end
## Per-request options ##
conn.get do |req|
req.url '/search'
req.options.timeout = 5 # open/read timeout in seconds
req.options.open_timeout = 2 # connection open timeout in seconds
end
RSPEC-RAILS
gem 'rspec-rails', '~> 3.4'
如果沒有用過 RSpec 都不能算是懂 Ruby 吧,respec_rails 顧名思義是將 rspec 集成至 rails 中的測試框架了:
require "spec_helper"
describe User do
it "orders by last name" do
lindeman = User.create!(first_name: "Andy", last_name: "Lindeman")
chelimsky = User.create!(first_name: "David", last_name: "Chelimsky")
expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
end
end
Devise
gem 'devise', '~> 3.5', '>= 3.5.2'
Devise 是一個用於快速構建基本用戶功能,如:注冊,登陸,找回密碼。 同時它還集成了第三方的登入支持,代碼也相當簡單:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 20
end
Devise 是一個大集成包,單看看它集成了什么就能知道到大至上的功能了:
- Database Authenticatable: 支持加密的身份驗證並能將驗證信息存儲於數據內。
- Omniauthable: 集成 OmniAuth 實現三方平台(如: Twitter, Facebook, 新浪微博, 騰訊 QQ)賬號登陸的支持。
- Confirmable: 發送郵件以驗證注冊用戶的身份。
- Recoverable: 支持密碼重置。
- Registerable:支持注冊新用戶。
- Rememberable: 支持自動登錄
- Trackable: 可跟蹤用戶的登入次數,時間戳和 IP
- Timeoutable: 支持自動用戶會話的過期
- Validatable: 可驗證用戶的郵件的與密碼的正確性,且可定制化。
- Lockable: 可以鎖定多次嘗試登錄失敗的用戶賬號。
如果沒有它,光想想要我們自己來碼上面的這些功能都夠浪費時間的。重點是每個項目都得用啊。
FACTORY_GIRL_RAILS
gem 'factory_girl_rails'
Factory Girl可能是ROR測試中最常用到的數據工廠,沒有它也只能手工寫Fixture了。不解釋了,它太常用了。
# spec/factories/user.rb
FactoryGirl.define do
factory :user do
first_name "Andy"
last_name "Lindeman"
end
end
# spec/models/user_spec.rb
require "spec_helper"
describe User do
it "orders by last name" do
lindeman = create(:user)
chelimsky = create(:user, first_name: "David", last_name: "Chelimsky")
expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
end
end
Better Errors
gem "better_errors"
它用一個更好的,更有用的錯誤頁替換標准的 Rails 錯誤頁面,對 Rack middleware 也同樣有效。
4百多萬的下載,可見美觀是很能吸引我們這些外觀第一的程序員的。
twitter-bootstrap-rails
gem "therubyracer"
gem "less-rails"
gem "twitter-bootstrap-rails"
來自 Twitter 的 Bootstrap,是一套完成的前台 CSS 框架。以簡潔,優雅著稱於世。被無數攻城獅所青睞,又讓無數程序猿審美疲勞。不用不行啊~
分頁控件
will_paginate
gem 'will_paginate', '~> 3.0.6'
Kaminari
gem 'kaminari'
Kaminari 支持多種的 ORM (ActiveRecord, Mongoid) 和多種的Web框架 (Rails, Sinatra, Grape), 以及多種的模板引擎 (ERB, Haml, Slim).
從數字上兩者都只在伯仲之間,只是will_paginate 比較老, 應用案例較多, kaminari 更新, 性能和兼容性更好。
計划任務
有時候一些任務的執行會很慢,而這些任務我們並不要求需要馬上返回結果 (比如:發送郵件,生成圖片縮略圖),那我們可以選擇將這些任務放到后台執行,以便於頁面不會長時間等待執行,我們還是將其統稱為計划任務吧。
在這方面的有不少出色的 gem, 其粉絲也不在少數
Resque
gem 'resque', '~> 1.25', '>= 1.25.2'
Resque 是一個基於 Redis 的后台任務處理gem。后台工作可以是任何一個Ruby類或者模塊。
Resque 相比於 DelayedJob 會是一個更加重型的gem。與 DelayedJob 的不同之處主要有三:
- 它是一個用於創建、查詢、處理 的 Ruby 庫
- 它是一個起動后台處理Worker的Rake任務。
- 它是一個Sinatra app 用於檢測隊列、工作和Workers.
class Archive
@queue = :file_serve
def self.perform(repo_id, branch = 'master')
repo = Repository.find(repo_id)
repo.create_archive(branch)
end
end
class Repository
def async_create_archive(branch)
Resque.enqueue(Archive, self.id, branch)
end
end
Sidekiq
gem 'sidekiq'
號稱性能要比 Reque 和 delayed_job 都要高,具體的數據你可以上它們的 GitHub 上看,有一個完整的對比表。但明顯在程序員的受歡迎度上還是要差於 Resque。
Resque 和 Sidekiq 都使用的 redis 作為任務數據存儲,這塊是差不多的,主要的區別還是在多任務處理的方式是不一樣的。
resque 使用的是一個 worker 通過 fork 方式來產生多個 worker 處理多個任務,而 sidekiq 是一個 worker 使用的 Thread 方式產生多個線程 處理多個任務。
那 fork 方式和 thread 方式有什么區別呢?
fork 方式
fork 一個進程,操作系統會建立一個獨立分開的地址空間,並且從父進程復制所有的內存片段到這個地址里面去。 這就意味着對於操作系統來說,對於 fork 的進程切換上下文,因為需要保存和加載所有數據,所以代價更大。 而且如果父進程死掉了,這些 fork 的子進程沒有退出的話,將會變成僵屍進程。
thread 方式
多線程的話是共享地址空間,內存並且多線程之間的交互也比較方便。而且你也不用擔心僵屍進程的問題,一旦進程死掉, 所有的線程會自動被殺掉。但這種方式也有缺點,你必須保證代碼是線程安全的,不然可能會引起麻煩。
不難得出
- resque 比 sidekiq 更消耗內存
- resque 的 worker 代碼沒有必要擔心線程安全問題,但 sidekiq 必須考慮
DELAYED_JOB
gem 'delayed_job_active_record'
DelayedJob 是一個輕量型的gem,使用起來也相當的簡單,而且它可以配合一個 progress bars 控件檢測任務的執行進度(可能這也是它除了輕量以外的最大特點)。
# without delayed_job
Notifier.signup(@user).deliver
# with delayed_job
Notifier.delay.signup(@user)
# with delayed_job running at a specific time
Notifier.delay(run_at: 5.minutes.from_now).signup(@user)
Whenever
gem 'whenever', :require => false
Linux 里面有 Cron 可以幫助我們定期執行一些任務,但是 Cron 手動寫起來很是麻煩,尤其是前面時間周期的定義, Whenever 可以幫助我們用更人性化的方式編寫 Cron 任務,看看出他的示例代碼:
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
every 1.day, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end
every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
runner "SomeModel.ladeeda"
end
every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
runner "Task.do_something_great"
end
every '0 0 27-31 * *' do
command "echo 'you can use raw cron syntax too'"
end
# run this task only on servers with the :app role in Capistrano
# see Capistrano roles section below
every :day, :at => '12:20am', :roles => [:app] do
rake "app_server:task"
end
它的 DSL 很簡單,直接,暴力易懂!
我個人是推薦使用 Resque 的。
上傳組件
Paperclip
gem "paperclip", "~> 4.3"
Paperclip 是老牌產品了,也是幾乎絕大多數項目都有在用它,它可以幫你處理上傳圖片,裁減,定義不同的圖片尺寸,幾乎很完美。(with the support of ImageMagick)
# Rail4
class User < ActiveRecord::Base
has_attached_file :avatar, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :avatar, content_type: /\Aimage\/.*\Z/
end
Carrierwave
gem 'carrierwave'
Carrierwave 是后起之秀,功能和 Paperclip 差不多,但它還可以管理除圖片之外的東西,而且靈活性更高。
對比
Paperclip 官方只支持 ActiveRecord 但相對穩定, 而 Carrierwave 比較靈活支持更多的 ORM, 比如 mongoid
If you feel adventurous, you can try refile from the creators of carrierwave.
表單
Rails 為我們帶來和一改傳統的表單構件方式,但是經過實際的使用,我們漸漸發覺這樣依然還是不夠“敏捷”,我們需要更加簡便並具有更細致規范的表單,所以有了 Formtastic ,它用起來比 Rails 默認的 form 更加簡潔,但是卻具有更多的功能,你可以為每個字段設定 help-text 放到文本框下面,並可以走 I18n 的方式設置語言。simple_form 和 Formtastic 功能類似,但它的寫法還要簡單一些。
SIMPLE_FORM
gem 'simple_form'
SimpleForm 在用法上與 Formtastic 類似,同樣很好的支持了I18n、表間關聯、嵌套表單和表單驗證等常用的功能。SimpleForm 從 2.0 開始,在可定制性上有質的突破(Twitter Bootstrap 在里邊起了很關鍵的作用),現在的它更像是一個 Form Builder 框架,可以很方便的對它進行設置和擴展。
看看 simple_form 的用法 :
= simple_form_for @user do |f|
= f.input :username, label: 'Your username please'
= f.input :password, hint: 'No special characters.'
= f.input :email, placeholder: 'user@domain.com'
= f.input :remember_me, inline_label: 'Yes, remember me'
= f.button :submit
Formtastic
gem 'formtastic', '~> 3.0'
Formtastic 的主要缺點在於對HTML輸出的可定制性上不夠靈活。目前的系統中,想要滿足各種表單的需求,就需要在每個表單頁寫很多重復的代碼進行設置,甚至很多頁面都在使用 Rails 原生的 Form Builder,這樣做維護量太大。
<%= semantic_form_for @post do |f| %>
<%= f.inputs do %>
<%= f.input :title %>
<%= f.input :body %>
<%= f.input :section, :as => :radio %>
<%= f.input :categories %>
<%= f.input :created_at, :as => :string %>
<% end %>
<%= f.actions do %>
<%= f.action :submit, :as => :button %>
<%= f.action :cancel, :as => :link %>
<% end %>
<% end %>
Grape
gem 'grape'
隨着 Mobile App 的增多,很多時候我們在做用 Rails 做 API Base 項目時,rails 自帶的 C 和 V 層顯得過於繁雜,grape 可以幫助我們快速的構建和 Rails 完美融合的 API 接口。
module Twitter
class API < Grape::API
version 'v1', using: :header, vendor: 'twitter'
format :json
prefix :api
helpers do
def current_user
@current_user ||= User.authorize!(env)
end
def authenticate!
error!('401 Unauthorized', 401) unless current_user
end
end
resource :statuses do
desc 'Return a public timeline.'
get :public_timeline do
Status.limit(20)
end
desc 'Return a personal timeline.'
get :home_timeline do
authenticate!
current_user.statuses.limit(20)
end
desc 'Return a status.'
params do
requires :id, type: Integer, desc: 'Status id.'
end
route_param :id do
get do
Status.find(params[:id])
end
end
desc 'Create a status.'
params do
requires :status, type: String, desc: 'Your status.'
end
post do
authenticate!
Status.create!({
user: current_user,
text: params[:status]
})
end
desc 'Update a status.'
params do
requires :id, type: String, desc: 'Status ID.'
requires :status, type: String, desc: 'Your status.'
end
put ':id' do
authenticate!
current_user.statuses.find(params[:id]).update({
user: current_user,
text: params[:status]
})
end
desc 'Delete a status.'
params do
requires :id, type: String, desc: 'Status ID.'
end
delete ':id' do
authenticate!
current_user.statuses.find(params[:id]).destroy
end
end
end
end
CANCANCAN
gem 'cancancan', '~> 1.10'
它是 CanCan 項目的代替品,它其實就是為我們的應用加入操作權限控制,而且比較好的地方是可以將所有的操作權限放在至到一個獨立的文件之中。
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
而它的另一個比較新后來者就可以數 pundit 了, 由於在RubyGems上的下載量才7萬多,所以就不獨列出數了。但值得注意的是它在GitHub上的start是6K多,已超越CanCanCan的Repository。
如果有做過操作權限控制的朋友可能都會發現,操作極權限控制是很耗費性能的,而 pundit 則號稱在性能上會超越 CanCanCan,
Pundit 更為模塊化,對於體量較大的程序我覺得更為之合適,至少不會寫出一個幾百行的大文件出來,不利於維護。
ActiveAdmin
gem 'activeadmin', github: 'activeadmin'
這是一個相當不錯的管理界面應用gem, 基本不需要做什么需求就能上項目了。從RubyGems的百萬級下載量也可以得知其受歡迎的程度了。感覺上是有點仿 Wordpress 的 Dashboard。
我個人是很喜歡 ActivateAdmin 的DSL定義的,因為既簡單又快速:
ActiveAdmin.register Product do
scope :all, default: true
scope :available
scope :drafts
filter :title
filter :author, as: :select, collection: ->{ Product.authors }
filter :price
filter :create_at
index do
column :title
column "Price", sortable: :price do |product|
number_to_currency product.price
end
defualt_actions
end
end
這樣的代碼幾乎就是秒懂,不解釋了。這家伙誰用誰說好 ^_^
他們的官網也做得挺好的,這里是一些關於 ActivateAdmin 的資源鏈接:
相關 gem
rails_admin
$ rails g rails_admin:install
與 ActiveAdmin 相比 rails_admin 就遜色的多了,但在 GitHub 上卻表現不俗。在代碼質量上其實兩者相去不遠,只是 ActiveAdmin 更好看一些,而 rails_admin 的界面就做得有點渣,要上項目的話必須得作出很多的修改。
以下是 rails_admin 的特色:
- 對任何數據都可支持 CRUD
- 自定義操作
- 自動化表單驗證
- 支持查找與過濾
- 可以將數據導出為 CSV/JSON/XML 格式
- 支持 Devise 的身份驗證
- 支持 CanCanCan 或 Pundit 的權限判定
- 通過 PaperTrail 支持用戶操作歷史
- 支持多種ORM
- ActiveRecord
- Mongoid
Sunspot
gem 'sunspot_rails'
gem 'sunspot_solr' # optional pre-packaged Solr distribution for use in development
Sunspot 是一個 Solr 搜索引擎的 Ruby 庫。它基於 RSolr 庫構建,提供低級別的 Solr 集成接口。它的定義很簡單,使用也相當容易,用DSL就可索引對象和啟用搜索了。
它的主要特點:
- 全文搜索
- ActiveRecord
- 英文分詞
ActivateRecord 定義 可搜索對象
class Post < ActiveRecord::Base
searchable do
text :title, :body
text :comments do
comments.map { |comment| comment.body }
end
boolean :featured
integer :blog_id
integer :author_id
integer :category_ids, :multiple => true
double :average_rating
time :published_at
time :expired_at
string :sort_title do
title.downcase.gsub(/^(an?|the)/, '')
end
end
end
搜索
Post.search do
fulltext 'best pizza'
with :blog_id, 1
with(:published_at).less_than Time.now
order_by :published_at, :desc
paginate :page => 2, :per_page => 15
facet :category_ids, :author_id
end
小結
我這里沒有列出 Rails 生成的那些常用 gem ,以上的都是一些我收集和常用的 gem 希望能對大家有用。
另外,如果您收藏了更好的 gem 希望能在本文留評,而且請注明 gem 的作用和 RubyGems 上的下載鏈接,給更多的Ruby的愛好者一個綜合性的資源匯總,Thanks!