Threads and processes in a Capybara/Selenium session

TLDR: This card explains which threads and processes interact with each other when you run a Selenium test with Capybara. This will help you understand "impossible" behavior of your tests.


When you run a Rack::Test (non-Javascript) test with Capybara, there is a single process in play. It runs both your test script and the server responding to the user interactions scripted by your test.

A Selenium (Javascript) test has a lot more moving parts:

  1. One process runs your test script. This is the process you...

Careful when writing to has_many :through associations

tl;dr: Using has_many associations with a :through option can lead to lost or duplicate records. You should avoid them, or only use them to read records.

Consider this:

class User < ActiveRecord::Base
end

class Party < ActiveRecord::Base
  has_many :invitations
  has_many :users, through: :invitations, include: :user, order: 'users.name'
end

class Invitation < ActiveRecord::Base
  belongs_to :party
  belongs_to :user
  
  after_create :send_invite
  
  def send_invite
  ...

Auto-coerced virtual attributes with Virtus

We've since created ActiveType which has a restricted subset of Virtus' features. It might be enough for your needs.

We sometimes give our ActiveRecord models virtual attributes for values that don't need to be stored permanently.

When such a virtual attribute should contain integer values you might get unexpected behavior with forms, because every param is a string and you don't get the magic type casting that Rails would give you if it ...

Whitelist Carrierwave attributes correctly

Say you have a User with a Carrierwave attribute #avatar:

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end

When whitelisting the avatar field in the controller, you might do this:

params[:user].permit(:avatar)

But you probably want this:

params[:user].permit(:avatar, :avatar_cache, :remove_avatar)

In this example:

  • :avatar_cache allows a newly upload image to persist through form roundtrips in the case of validation errors (something that isn't possibl...

Alan Klement: Replacing The User Story With The Job Story

I've written about the problem with user stories before. At the time, I found it better to just have the team talk over proposed changes to the product. This worked great when the team had gelled and the product is very mature; however, now I'm working with a new team and building a product from scratch. In this case, because our canvas is blank, we are having trouble getting on the same page when it comes to customer motivations, events and expectations. But today, things have turned around. I've come across a great way to use the jobs to...

Let the browser choose the protocol

Use protocol independent URLs whenever possible so that the browser will choose the protocol related to the protocol which the page is delivered with.

Example issues

  • When your page is delivered via https and you provide a youtube video only via http the most browsers (e.g. Firefox, Chrome) won't display the video.
  • When you deliver your youtube video via https://youtu.be/jyElDp98HdI your test which checks that the embeded video is rendered in the view will fail because your test server doesn't use https

Solution

Let your lin...

Get Moving With Angular 1.2 Animation and Animate.css

Motion is quickly becoming one of the most important emerging techniques in building a quality user experience on the web. Angular 1.2, currently in release candidate form, provides an overhaul of Angular's animation system and makes it spectacularly easy to bring your interface to life.

International Address Fields in Web Forms :: UXmatters

Advice for address forms that work with address structures from multiple countries.

Enable NewRelic monitoring [for Rails] on specific hosts only

If you need to enable NewRelic monitoring on certain machines within the same Rails environment, a simple solution is to utilize the respective hostnames of you machines.

For example, if you have 8 application servers (e.g. app1.example.com, app2.example.com, ...) and want to enable NewRelic on app1 and app2 only, utilize those steps to do so:

  1. Put the attached file into your config directory (config/custom_new_relic_configuration.rb).
  2. Specify on which hosts NewRelic should be enabled (see NEWRELIC_HOSTS constant and list ...

A simpler default controller implementation

Rails has always included a scaffold script that generates a default controller implementation for you. Unfortunately that generated controller is unnecessarily verbose.

When we take over Rails projects from other teams, we often find that controllers are the unloved child, where annoying glue code has been paved over and over again, negotiating between request and model using implicit and convoluted protocols.

We prefer a different approach. We believe that among all the classes in a Rails project, controllers are some of the hardest to...

How to not repeat yourself in Cucumber scenarios

It is good programming practice to Don't Repeat Yourself (or DRY). In Ruby on Rails we keep our code DRY by sharing behavior by using inheritance, modules, traits or partials.

When you reuse behavior you want to reuse tests as well. You are probably already reusing examples in unit tests. Unfortunately it is much harder to reuse code when writing integration tests with Cucumber, where you need to...

Implementing social media "like" buttons: Everything you never wanted to know

So you client has asked you to implement a row of buttons to like the URL on Facebook, Twitter and Google+. Here are some things you should know about this.

0. Security considerations

Each "like" button is implemented by including a Javascript on your site. This means you are running fucking remote code on your page. You are giving Facebook, Twitter and Google+ full permission to e. g. copy user cookies. Check with your client if she is cool with that. Also note that if you're site is suggesting security by operating under HTTPS ...

RailsPanel chrome extension

Chrome extension that shows all info from your rails log (like parameters, response times, view rendering times, DB requests) inside a chrome panel.

Rails 3/4: How to add routes for specs only

If you want to have routes that are only available in tests (e.g. for testing obscure redirects), you can use the with_routing helper -- but that one destroys existing routes which may break a specs that require them to work.

To keep both "regular" and test routes, do this:

class MyApplicationController < ActionController::Base
  def show
    render text: 'Welcome to my application'
  end
end

test_routes = Proc.new do
  get '/my_application' => 'my_application#show'
end
Rails.application.routes.ev...

You don't need each, collect or select in Coffeescript

Working with lists in Javascript is painful because the native Array class is so poorly designed.

One way to reduce the pain is to to use Underscore.js's functions like _.each, _.map or _.select, which unfortunately clutters your code with awkward calls to the _ helper.

Fortunately when you use CoffeeScript you don't need any of that. CoffeeScript has a very versatile for keyword that can do anything that each, collect or select can do. Enjoy!

each

f...

PostgreSQL cheat sheet for MySQL lamers

So you're switching to PostgreSQL from MySQL? Here is some help...

General hints on PostgreSQL

  • \? opens the command overview
  • \d lists things: \du lists users, \dt lists tables etc

Command comparison

Description MySQL command PostgreSQL equivalent
Connect to the database mysql -u $USERNAME -p sudo -u postgres psql
Show databases SHOW DATABASES; \l[ist]
Use/Connect to a database named 'some_database' USE some_database; \c some_dat...

Disable text-transforms in Selenium tests

Using text-transform: uppercase - especially on form labels - can cause you serious headaches in Selenium tests. Sometimes the web driver will see the uppercase text, sometimes it won't, and umlauts will be a problem as well.

Simply disable it in tests, by

  • adding a body class for tests

    %body{'data-environment' => Rails.env}
    
  • overriding the transforms

    [data-environment="test"] *
      text-transform: none !important
    

List of Compass Mixins

Since we are migrating from our homegrown mixins.sass and helpers.sass to Compass, here is a list of all the mixins provided by Compass.

Compiling Javascript template functions with the asset pipeline

The asset pipeline (which is actually backed by sprockets) has a nice feature where templates ending in .jst are compiled into Javascript template functions. These templates can be rendered by calling JST['path/to/template'](template: 'variables'):

<!-- templates/hello.jst.ejs -->
<div>Hello, <span><%= name %></span>!</div>

// application.js
//= require templates/hello
$("#hello").html(JST["templates/hello"]({ name: "Sam" }));

Whatever is in the <% ... %> is evaluated in Javascript...

Getting rid of space between inline-block elements

When two elements with display: inline-block are sitting next to each other, whitespace between becomes a space character.

Solutions, in decreasing order of awesomeness:

  1. Don't have whitespace between two elements! See Whitespace Removal in Haml if you're using Haml.
  2. Don't use inline-block. Use floating elements instead (don't forget to clear them!).
  3. Try to compensate for the space with a negative margin. Unfortunately you will never be able to negate ...

Font Awesome: List of Unicode glyphs and HTML entities

A list of FontAwesome icons in the form of copyable Unicode characters or HTML entities.

You might prefer to use FontAwesome by simply typing out these characters instead of using CSS classes. Of course you need to then give the containing element as style:

font-family: FontAwesome

Nested controller routes (Rails 2 and 3)

In order to keep the controllers directory tidy, we recently started to namespace controllers. With the :controller option you can tell Rails which controller to use for a path or resource. For nested resources, Rails will determine the view path from this option, too.

That means the following code in routes.rb

resources :users do
  resource :profile, controller: 'users/profiles' #[1]
end

… makes Rails expect the following directory structure:

app/
  controllers/
    users/
      profiles_controller.rb
    users_control...

Rails: Output helpers for migrations

When you're writing migrations that do more than changing tables (like, modify many records) you may want some output. In Rails > 3.1 you have two methods at hand: announce and say_with_time.

In the migration:

class AddUserToken < ActiveRecord::Migration

  class User < ActiveRecod::Base; end

  def up
    add_column :users, :token, :string
    
    announce "now generating tokens"
    User.find_in_batches do |users|
      say_with_time "For users ##{users.first.id} to ##{users.last.id}" do
        users.each do |user|
        ...

Font sizing with rem - Snook.ca

CSS3 comes with new unit rem. It works like em but it is always relative to the <html> element instead of the parent element.

rem units are supported by all browsers and IE9+.