Ruby On Rails 常用的精品Gem汇总
无价的 Gems
一个最重要的编程理念是 "不要重造轮子!" 。若你遇到一个特定问题,你应该要在你开始前,看一下是否有存在的解决方案。下面是一些在很多 Rails 项目中 "无价的" gem 列表(全部兼容 Rails 3.1):
- active_admin - 有了 ActiveAdmin,创建 Rails 应用的管理介面就像儿戏。你会有一个很好的仪表盘,图形化 CRUD 介面以及更多东西。非常灵活且可定制化。
- better_errors - Better Errors 用更好更有效的错误页面,取代了 Rails 标准的错误页面。不仅可用在 Rails,任何将 Rack 当作中间件的 app 都可使用。
- bullet - Bullet 就是为了帮助提升应用的效能(通过减少查询)而打造的 gem。会在你开发应用时,替你注意你的查询,并在需要 eager loading (N+1 查询)时、或是你在不必要的情况使用 eager loading 时,或是在应该要使用 counter cache 时,都会提醒你。
- cancan - CanCan 是一个权限管理的 gem, 让你可以管制用户可存取的支援。所有的授权都定义在一个档案里(ability.rb),并提供许多方便的方法,让你检查及确保整个应用内权限是否是可得的。
- capybara - Capybara 旨在简化整合测试 Rack 应用的过程,像是 Rails、Sinatra 或 Merb。Capybara 模拟了真实用户使用 web 应用的互动。 它与你测试在运行的驱动无关,并原生搭载 Rack::Test 及 Selenium 支持。透过外部 gem 支持 HtmlUnit、WebKit 及 env.js 。与 RSpec & Cucumber 一起使用时工作良好。
- carrierwave - Rails 最后一个文件上传解决方案。支持上传档案(及很多其它的酷玩意儿的)的本地储存与云储存。图片后处理与 ImageMagick 整合得非常好。
- client_side_validations - 一个美妙的 gem,替你从现有的服务器端模型验证自动产生 Javascript 用户端验证。高度推荐!
- compass-rails - 一个优秀的 gem,添加了某些 css 框架的支持。包括了 sass mixin 的蒐集,让你减少 css 文件的代码并帮你解决浏览器兼容问题。
- cucumber-rails - Cucumber 是一个由 Ruby 所写,开发功能测试的顶级工具。 cucumber-rails 提供了 Cucumber 的 Rails 整合。
- devise - Devise 是 Rails 应用的一个完整解决方案。多数情况偏好使用 devise 来开始你的客制验证方案。
- fabrication - 一个很好的假数据产生器(编辑者的选择)。
- factory_girl - 另一个 Fabrication 的选择。一个成熟的假数据产生器。 Fabrication 的精神领袖先驱。
- ffaker - 实用的 gem 来产生仿造的数据(名字、地址,等等)。
- feedzirra - 非常快速及灵活的 RSS 或 Atom 种子解析器。
- friendly_id - 透过使用某些具描述性的模型属性,而不是使用 id,允许你创建人类可读的网址。
- globalize3 - Globalize3 是 Globalize 的后继者,针对 ActiveRecord 3.x 设计。基于新的 I18n API 打造而成,并帮 ActiveRecord 模型添加了事务功能。
- guard - 极佳的 gem 监控文件变化及任务的调用。搭载了很多实用的扩充。远优于 autotest 与 watchr。
- haml-rails - haml-rails 提供了 Haml 的 Rails 整合。
- haml - Haml 是一个简洁的模型语言,被很多人认为(包括我)远优于 Erb。
- kaminari - 很棒的分页解决方案。
- machinist - 假数据不好玩,Machinist 才好玩。
- rspec-rails - RSpec 是 Test::MiniTest 的取代者。我不高度推荐 RSpec。 rspec-rails 提供了 RSpec 的 Rails 整合。
- simple_form - 一旦用过 simple_form(或 formatastic),你就不想听到关于 Rails 缺省的表单。它是一个创造表单很棒的DSL。
- simplecov-rcov - 为了 SimpleCov 打造的 RCov formatter。若你想使用 SimpleCov 搭配 Hudson 持续整合服务器,很有用。
- simplecov - 代码覆盖率工具。不像 RCov,完全兼容 Ruby 1.9。产生精美的报告。必须用!
- slim - Slim 是一个简洁的模版语言,被视为是远远优于 HAML(Erb 就更不用说了)的语言。唯一会阻止我大规模地使用它的是,主流 IDE 及编辑器对它的支持不好。但它的效能是非凡的。
- spork - 一个给测试框架(RSpec 或 现今 Cucumber)用的 DRb 服务器,每次运行前确保分支出一个乾净的测试状态。 简单的说,预载很多测试环境的结果是大幅降低你的测试启动时间,绝对必须用!
- sunspot - 基于 SOLR 的全文检索引擎。
这不是完整的清单,以及其它的 gem 也可以在之后加进来。以上清单上的所有 gems 皆经测试,处于活跃开发阶段,有社群以及代码的质量很高。
缺陷的 Gems
这是一个有问题的或被别的 gem 取代的 gem 清单。你应该在你的项目里避免使用它们。
- rmagick - 这个 gem 因大量消耗内存而声名狼藉。使用 minimagick 来取代。
- autotest - 自动测试的老旧解决方案。远不如 guard 及 watchr。
- rcov - 代码覆盖率工具,不兼容 Ruby 1.9。使用 SimpleCov 来取代。
- therubyracer - 极度不鼓励在生产模式使用这个 gem,它消耗大量的内存。我会推荐使用
node.js
来取代。
这仍是一个完善中的清单。请告诉我受人欢迎但有缺陷的 gems 。
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!