https://github.com/rails-api/active_model_serializers
- Customize fields to be serialized to json
class SomeResource < ActiveRecord::Base
# columns: title, body
end
class SomeSerializer < ActiveModel::Serializer
attribute :title, key: :name
attributes :body
end
https://github.com/mbleigh/acts-as-taggable-on
- Powerful support for tags
class User < ActiveRecord::Base
acts_as_taggable_on :skills, :interests
end
@user.skill_list = "joking, clowning, boxing"
@user.skill_list.add("coding")
@user.skill_list
# => ["joking", "clowning", "boxing", "coding"]
User.tagged_with("awesome")
User.tagged_with(["awesome", "cool"], :any => true)
https://github.com/tcocca/acts_as_follower
- For the next "Facebook For X", implement a follower model
class Book < ActiveRecord::Base
...
acts_as_followable
...
end
class User < ActiveRecord::Base
...
acts_as_follower
...
end
user.follow(book)
user.stop_following(book)
user.following?(book)
user.following_by_type('Book')
book.followers
book.block(user)
https://github.com/airbrake/airbrake
- Error tracking and notification emails
rails g airbrake PROJECT_ID PROJECT_KEY
[mobius-backend-staging] Development no implicit conversion of Date into String
---
Error Message:
no implicit conversion of Date into String
Where:
maker_spaces#show
[PROJECT_ROOT]/app/controllers/admin/maker_spaces_controller.rb, line 80
https://github.com/segmentio/analytics-ruby
- Connects to segment.io, an analytics data broker that can talk to different tools
# Identify the user for the people section
analytics.identify(
{
user_id: user.id,
traits: {
email: user.email,
first_name: user.first_name,
last_name: user.last_name
}
}
)
# Track a user event
analytics.track(
{
user_id: user.id,
event: 'Created Account'
}
)
- Print usefully
puts MakerSpace.first
#<MakerSpace:0x007fae73860118>
awesome_print MakerSpace.first
#<MakerSpace:0x007fae707d32e8> {
:id => "110d05bc-c7ca-4481-b342-f0ede9ad35a0",
:created_at => Thu, 07 Jan 2016 05:48:33 EST -05:00,
:updated_at => Thu, 07 Jan 2016 05:48:33 EST -05:00,
:name => "Pappalardo Lab",
:location => "3-069",
:latitude => 42.35898,
:longitude => -71.092373,
:image => "http://i.imgur.com/fSwF1aQ.jpg",
:access_requirements => "You must be enrolled in 2.007",
:address => "33 Massachusetts Ave",
:city => "Cambridge",
:state => "MA",
:postal_code => "02139",
:phone => "6175551234",
:description => "The Pappalardo Lab"
}
https://github.com/aws/aws-sdk-ruby
- Wide-ranging gem for connecting with Amazon Web Services... services
s3 = Aws::S3::Client.new
resp = s3.list_buckets
resp.buckets.map(&:name)
#=> ["bucket-1", "bucket-2", ...]
https://github.com/flyerhzm/bullet
- Helps identify N+1 queries and unused eager loading
clients = Client.limit(10)
clients.each do |client|
puts client.address.postcode
end
vs.
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
https://github.com/trptcolin/consistency_fail
- Ensure that your db uniqueness restrictions match your
validates_uniqueness
claims
$ consistency_fail
There are calls to validates_uniqueness_of that aren't backed by unique indexes.
--------------------------------------------------------------------------------
Model Table Columns
--------------------------------------------------------------------------------
User users (authentication_token)
--------------------------------------------------------------------------------
There are calls to has_one that aren't backed by unique indexes.
--------------------------------------------------------------------------------
Model Table Columns
--------------------------------------------------------------------------------
User kerberos_identities (user_id)
--------------------------------------------------------------------------------
Hooray! All calls to has_one_with_polymorphic are correctly backed by a unique index.
https://github.com/magnusvk/counter_culture
- Utilities for storing counts of children in a column on the parent
add_column :categories, :products_count, :integer, :null => false, :default => 0
class Product < ActiveRecord::Base
belongs_to :category
counter_culture :category
end
class Category < ActiveRecord::Base
has_many :products
end
Category.first.products_count
https://github.com/petergoldstein/dalli
- Connect rails to memcached
- Cleans databases (generally for testing (generally by people not at Intrepid))
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.around(:each) do |example|
DatabaseCleaner.cleaning do
example.run
end
end
end
https://github.com/drapergem/draper
- Decorators for presentation logic
BAD:
# app/helpers/articles_helper.rb
def publication_status(article)
if article.published?
"Published at #{article.published_at.strftime('%A, %B %e')}"
else
"Unpublished"
end
end
GOOD:
# app/decorators/article_decorator.rb
class ArticleDecorator < Draper::Decorator
delegate_all
def publication_status
if published?
"Published at #{published_at}"
else
"Unpublished"
end
end
def published_at
object.published_at.strftime("%A, %B %e")
end
end
@article = Article.first.decorate
https://github.com/thoughtbot/factory_girl_rails
- Factories for creating mock objects for testing
FactoryGirl.define do
factory :incident do
user
author
maker_space
sequence(:name) { |n| "Cut off #{n} fingers" }
notes "This totally happened"
severity "severe"
end
end
incident = create(:incident)
https://github.com/oscardelben/firebase-ruby
- Hosting and db
- Sort of heroku
- Claims to focus on "real-time" apps
https://github.com/ddollar/foreman
- For running and managing Procfile-based applications
- For a heroku-hosted project
foreman start
has given way to
heroku local
https://github.com/ankane/groupdate
- Query records and group by date
User.group_by_day(:created_at).count
Groupdate.time_zone = "Pacific Time (US & Canada)"
User.group_by_week(:created_at, time_zone: "Pacific Time (US & Canada)").count
# {
# 2013-03-10 00:00:00 PST => 70,
# 2013-03-17 00:00:00 PDT => 54,
# 2013-03-24 00:00:00 PDT => 80
# }
https://github.com/peterhellberg/hashids.rb
- Alternative to
create_table :users, id: :uuid
https://github.com/jnunemaker/httparty
- Convenience methods arround http requests
class StackExchange
include HTTParty
base_uri 'api.stackexchange.com'
def initialize(service, page)
@options = { query: {site: service, page: page} }
end
def questions
self.class.get("/2.2/questions", @options)
end
def users
self.class.get("/2.2/users", @options)
end
end
stack_exchange = StackExchange.new("stackoverflow", 1)
puts stack_exchange.questions
puts stack_exchange.users
https://github.com/ruby-json-schema/json-schema
- For validating json scheme
- Ended up being to heavy weight to use much
schema = {
"type" => "object",
"required" => ["a"],
"properties" => {
"a" => {"type" => "integer"}
}
}
data = {
"a" => 5
}
JSON::Validator.validate(schema, data)
https://github.com/amatsuda/kaminari
- Support for pagination
User.page(7).per(50)
https://github.com/arsduo/koala
- Wraps facebook APIs and auth
@graph = Koala::Facebook::API.new(oauth_access_token)
@graph.get_connections("me", "mutualfriends/#{friend_id}")
https://github.com/halogenandtoast/monban
- User management
Monban.config.sign_up_service.new(user_attributes).perform
Monban.config.authentication_service.new(user, current_password).perform
Monban.config.password_reset_service.new(user, password).perform
https://github.com/RubyMoney/money-rails
class Product < ActiveRecord::Base
register_currency :usd
monetize :price_cents
end
...
add_money :products, :price
https://github.com/ohler55/oj
- Fast JSON parser
https://github.com/thoughtbot/parity
- Shell commands for development, staging, and production parity for Heroku apps
production backup
development restore production
staging deploy
staging console
https://github.com/jfelchner/ruby-progressbar
def progressbar
@progressbar ||= ProgressBar.create(title: "#{title} (#{record_count - 1})",
starting_at: 0,
total: record_count)
end
def import!
progressbar.tap do |bar|
CSV.foreach(file_path, headers: true) do |row|
...
end
bar.finish
end
end
https://github.com/puma/puma
- alternative web server
- Restrict CRUD actions to certain users
- Scope records to those who should be able to view them
class IncidentPolicy < ApplicationPolicy
def create?
user.admin?
end
def show?
user.admin? || record.user == user
end
def index?
true
end
class Scope < Scope
def resolve
if user.admin?
scope.all
else
scope.where(user: user)
end
end
end
end
def index
incidents = policy_scope(Incident)
authorize incidents
render json: incidents
end
def show
incident = Incident.find(params[:id])
authorize incident
render json: incident
end
- Library/service for cross-platform (socket-based) push notifications
https://github.com/preston/railroady
- UML diagrams, etc.
https://github.com/heroku/rails_12factor
- Deployment configs, logging, etc. management
https://github.com/spilliton/randumb
Artist.order_by_rand.limit(3).all
https://github.com/croaky/recipient_interceptor
- Never accidentally send emails to real people from your staging environment.
https://github.com/bbatsov/rubocop
- Ruby linter with CLI and editor plugins
https://github.com/phstc/shoryuken
- Consume messages from AWS' Simple Queueing Service
https://github.com/thoughtbot/shoulda-matchers
- One-liner rspec tests for common functionality
describe Person do
it { should validate_presence_of(:name) }
end
- Easy background processing
class HardWorker
include Sidekiq::Worker
def perform(name, count)
# do something
end
end
HardWorker.perform_in(5.minutes, 'bob', 5)
https://github.com/plataformatec/simple_form
<%= simple_form_for(@maker_space, :url => admin_maker_spaces_path, :method => :post) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
<%= f.input :location %>
<%= f.input :latitude %>
<%= f.input :longitude %>
<%= f.input :image %>
<%= f.input :access_requirements %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
https://github.com/calebthompson/time_for_a_boolean
class Post < ActiveRecord::Base
time_for_a_boolean :deleted
end
post.deleted?
post.deleted = true
post.save
post.deleted_at
# <timestamp>
https://github.com/travisjeffery/timecop
- Manipulate time, as understood by Time.now, Date.today, and DateTime.now
joe = User.find(1)
joe.purchase_home()
assert !joe.mortgage_due?
# move ahead a month and assert that the mortgage is due
Timecop.freeze(Date.today + 30) do
assert joe.mortgage_due?
end
https://github.com/travis-ci/travis.rb
- Intreface with Travis CI
https://github.com/nomad/venice
- Apple IAP receipt validation
data = "(Base64-Encoded Receipt Data)"
if receipt = Venice::Receipt.verify(data)
...
end
https://github.com/bploetz/versionist
- Easily support different API versioning strategies
HTTP Header strategy Accept: application/vnd.mycompany.com; version=1,application/json
MyApi::Application.routes.draw do
api_version(:module => "V1", :header => {:name => "Accept", :value => "application/vnd.mycompany.com; version=1"}) do
match '/foos.(:format)' => 'foos#index', :via => :get
match '/foos_no_format' => 'foos#index', :via => :get
resources :bars
end
end
Path strategy /v3/foos
MyApi::Application.routes.draw do
api_version(:module => "V3", :path => {:value => "v3"}) do
match '/foos.(:format)' => 'foos#index', :via => :get
match '/foos_no_format' => 'foos#index', :via => :get
resources :bars
end
end
Request Parameter /foos?version=v2
MyApi::Application.routes.draw do
api_version(:module => "V2", :parameter => {:name => "version", :value => "v2"}) do
match '/foos.(:format)' => 'foos#index', :via => :get
match '/foos_no_format' => 'foos#index', :via => :get
resources :bars
end
end
https://github.com/hassox/warden
- User management
class V1::AuthenticatedController < V1::ApiController
def current_user
request.env['warden'].user
end
end
class AuthorizedConstraint
def matches?(request)
warden = request.env['warden']
warden && warden.authenticate!(:token_authentication_strategy)
end
end
# in routes.rb
constraints AuthorizedConstraint.new do
resources :users, only: [:show, :index, :update]
end
https://github.com/bblimke/webmock
- Stub web requests for tests
stub_request(:post, "www.example.com").
with(:body => "abc", :headers => { 'Content-Length' => 3 })
uri = URI.parse("http://www.example.com/")
req = Net::HTTP::Post.new(uri.path)
req['Content-Length'] = 3
res = Net::HTTP.start(uri.host, uri.port) do |http|
http.request(req, "abc")
end # ===> Success
https://github.com/ZeroPush/zero_push
- Easily send iOS push notifications