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:

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

Underscore.js Lo-Dash

General UI widgets

http://jqueryui.com/

Gem: jquery-ui-rails

Combox select

https://github.com/ivaynberg/select2

Gem: select2-rails

Date formating, parsing, etc.

http://momentjs.com/

Smart time ago

Gem: momentjs-rails

Money formatting

accounting.js - money and currency formatting, with optional excel-style column rendering

Charts

http://highcharts.com

Gem: highcharts-rails

Polyfills

Benchmarks

Benchmark.js

jQuery Plugins

Unheap - A tidy repository of jQuery plugins

Scrollorama

Maths

Mathjax

Video

PopcornMaker

Testing

Jasmine BDD

QUnit

CasperJS

Sinon.js

Typography

Kerning.js

Syntax Hightlighting

Prism

CoffeeScript

js2coffee

Prototyping

RoughDraft.js

A Box of Javascript Chocolates

Crazy Shit

theNewAesthetic.Js


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.

http://gruntjs.com

Video: “Grunt JavaScript Automation for the Lazy Developer” Video & article: “How to Build Your Own Custom jQuery”

Where we’ve used it so far

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:

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.