Tools, Gems, etc.
Tools for Testing
- PhantomCSS: takes screenshots captured by PhantomJS and compares them to baseline images using Resemble.js to test for rgb pixel differences. PhantomCSS then generates image diffs to help you find the cause.
Emails
Testing Emails in Development
To enable delivery of emails in development without having to restart your server, use my_mailer_instance.my_method.deliver!
instead of .deliver
- this is for debugging only, NEVER commit a .deliver!
as it ignores your environment’s perform_delivery
setting.
Different ways to catch/debug emails in development mode:
- mailcatcher gem that runs locally and shows emails in a simple web frontend
- mailtrap.io web service by Railsware, currently free
- MockSMTP MacOS app (14,49 €)
MockSMTP/mailcatcher setup in a Rails project
Given you won’t change MockSMTP/mailcatcher default settings (no one ever does that anyway), you can use this snippet in your app/config/environments/development.rb
:
Replace:
config.action_mailer.raise_delivery_errors = false
With:
begin
# if in development there's MockSMTP running, pass e-mails to it
TCPSocket.new('127.0.0.1', 1025).close
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025, :domain => "example.local"}
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
config.action_mailer.raise_delivery_errors = false
end
Use it to automatically serve email to MockSMTP, if it’s running.
Caching
If you have dynamic content somewhere in your layout you probably want to use fragment caching blocks over action caching.
Use the dalli
gem as a client for memcached
as cache store.
Make sure that caches are cleared on deployment. Here an example for the corresponding rake and deploy tasks:
lib/tasks/cache.rake:
namespace :cache do
desc "Clear cache (memcache etc.)"
task :clear => :environment do
Rails.cache.clear
end
end
config/deploy.rb:
namespace :cache do
desc "Clear cache (memcached etc.) after deployment"
task :clear, :roles => :app do
run "cd -- #{latest_release.shellescape} && #{rake} RAILS_ENV=#{rails_env.to_s.shellescape} cache:clear"
end
end
Pro-tipp: Don’t cache your csrf_meta_tag
;)
Invoices
For invoicing we’re using SalesKing. They have a great pool of ressources on github.
[TODO Jan]
Payment
Do’s and dont’s and hickups…
Paypal
Use Will-Paypal
[TODO Jan]
Other Payment Services
[TODO Jan]
Uploading files
The tools of choice for uploading files are carrierwave, fog and Amazon S3.
In very rare simple cases it might be enough to store files directly on the app server’s filesystem, but then you are tied to this one server and can’t add additiona app servers. If you should still do this, you need to remember to store files outside of the current release folder (e.g. in shared/system/uploads/
), otherwise they will be gone after the next deployment.
In S3 you should create 2 different buckets for staging and production. Bucket location should be Ireland (eu-west-1
). For security reasons, it’s also a best practice to create dedicated AWS users with limited AWS access (e.g. only for S3) through Amazon’s IAM service.
In development mode it’s probably simpler to keep on using your filesystem for storage.
This is what a typical config/initializers/carrierwave.rb
would look like:
CarrierWave.configure do |config|
if Rails.env.production? || Rails.env.staging?
config.storage = :fog
config.fog_credentials = {
:provider => 'AWS',
:region => 'eu-west-1',
:aws_access_key_id => '....',
:aws_secret_access_key => '....'
}
if Rails.env.production?
config.fog_directory = 'production-bucket'
elsif Rails.env.staging?
config.fog_directory = 'staging-bucket'
end
config.fog_public = false
else
config.storage = :file
end
config.enable_processing = false if Rails.env.test?
end
If you are dealing with absolutely, explicitly public files you can set config.fog_public
to true
, otherwise false
is the better option. In the later case the application will create links to the files on S3 that will expire after a certain time.
Fast tests
Zeus
zeus is a gem that will keep preloaded copies of your environment in the background so that tests, rake tasks, and rails commands will save those initial 20+ seconds. It is especially usefull for quickly running individual tests.
Here is a good blogpost on setting it up: http://robots.thoughtbot.com/post/40193452558/improving-rails-boot-time-with-zeus
Zeus Gotchas
- Zeus is picky about the format if you want to run tests on specific lines this is pretty much the only format that works
zeus rspec spec/path/test_case_spec.rb:12
zeus start
relies on the presence of all the right tables in the test database, otherwiese it will crash
You need to restart zeus if:
- your bundle changes
- your spec_helper or the factories loaded in the spec_helper change
- you’ve migrated your database
Static Content
For static content we recommend all our clients to use Markdown. It’s simple, we use it every day on GitHub and it’s just a good idea to agree on some standard.
Here are two links to get started with Markdown:
The easiest way to render Markdown in your views is to use the corresponding :markdown
filter from Haml.
// staticpage.html.haml:
%h1= t("static_content.somepage.title")
:markdown
#{t("static_content.somepage.body")}
For the markdown filter to work some Markdown parser gem needs to be installed. We recommend rdiscount
for that (Gotcha: Works only with Ruby 1.9.3). However the default implementation of the markdown filter is not very secure and convenient, so it’s recommended to define your own custom markdown filter by adding this code into an initializer:
# config/initializers/haml.rb
module MyApp
module Filters
module Markdown
include Haml::Filters::Base
lazy_require 'rdiscount'
def render(text)
ActionController::Base.helpers.sanitize ::RDiscount.new(text, :autolink).to_html
end
end
end
end
Taken from here
This will conveniently autolink links from your markdown and sanitize the output, stripping out all disallowed evil HTML tags while allowing safe tags. If the client will never ever need any HTML in his Markdown, you can even go as far as filtering all HTML like this:
def render(text)
::RDiscount.new(text, :filter_html, :autolink).to_html
end
As storage for your static content it makes sense to create a separate i18n .yml file. Something like this:
# config/locales/static_content.de.yml
static_content:
somepage:
title: "Foo"
body: |
Foo
Bar
Javacript Libs
Utility Belt
General UI widgets
Gem: jquery-ui-rails
Combox select
https://github.com/ivaynberg/select2
Gem: select2-rails
Date formating, parsing, etc.
Gem: momentjs-rails
Money formatting
accounting.js - money and currency formatting, with optional excel-style column rendering
Charts
Gem: highcharts-rails
Polyfills
- input placeholder text for IE: jquery-placeholder
Benchmarks
jQuery Plugins
Unheap - A tidy repository of jQuery plugins
Maths
Video
Testing
Typography
Syntax Hightlighting
CoffeeScript
Prototyping
Links
A Box of Javascript Chocolates
Crazy Shit
CSS Tools
### Code Generators css gradients please!
Favicons
- You want square, transparent pngs with round corners in the following resolutions: 57x57, 72x72, 114x114 and 144x144
- Then stitch it together with this online tool: http://iconogen.com
- Or better, on the command line, with imagemagick:
convert 57.png 72.png 114.png 144.png -colors 256 favicon.ico
Mobile Device Development Tools
Remote Debugging on Android using Google Chrome
Grunt
Grunt is a build tool running on node.js widely used by the JavaScript community to build and package libraries and projects. In the JavaScript world knowing it is quickly becoming as essential as knowing how to use Bundler in the Ruby world. It’s also an essential component of Yeoman.
Video: “Grunt JavaScript Automation for the Lazy Developer” Video & article: “How to Build Your Own Custom jQuery”
Where we’ve used it so far
- Gruner & Jahr FTD.de Backbone app (replacing Middleman, using Google Closure compiler to minify JS) (Philipp & Paul)
- Axel Quack Singlepage-Backbone-App (Paul)
What it can do
- watcher processes triggered by modified files when you’re developing
- multiple build targets - b/c you don’t want concatenation and minification when developing
- concatenate and minify JS
- compile CoffeeScript, HAML(-Coffee), JS templates (handlebars etc.), markdown …
- livereload
- provide a server process
- cachebusting
- (Compile SASS) - with compilation speed penalty; i’m currently using a separate Ruby compass watcher for this; might get better once Compass has been ported to JS like SASS
Where it shines
- de-facto standard for building JS projects
- support for anything related to JavaScript is a breeze: JS linting, hinting, compressing etc.
- excellent CoffeeScript and HAML-Coffee support
Where it’s got to get better
- lots of stuff to configure still…
- configuration of some plugins doesn’t entirely conform to slowly establishing community standards.
- some plugins aren’t well-maintained, lacking tests, documentation and participation
How to install and set up
- install node.js (homebrew)
- install npm (node package manager, like bundler) (afaicr also with homebrew
- install grunt with:
npm install -g grunt-cli
- set up your package.json (behaves much like a Gemfile) and run
npm install
OR simply install a new package with:npm install grunt-contrib-coffee --save-dev
(will automatically be added to the package.json) - configure build tasks in your Gruntfile (example here: http://gruntjs.com/sample-gruntfile)
Trivia
- developed and sponsored by Bocoup.
- two important Grunt authors:
- Ben Alman
- Sindre Sorhus - looks like he’s good friends with Mike already ;)
State Machine
If an application requires the usage of a state machine, try to use https://github.com/aasm/aasm, because it is maintained by our friend Thorsten Böttger.