How to test resource_controller hooks

When using the resource_controller gem you often hook onto events like this:
update.before do
do_something
end

For testing such things in your controller you should -- as always -- not trigger something that eventually calls the thing you want.\
Instead, in your specs, have resource_controller run those hooks like it does itself. Like that:

describe 'before update' do
 ...

SSL: Build a Certificate signing request (CSR)

In order to request a SSL certificate from any dealer, you usually need a CSR certificate. As both the CSR as well as key are created in this step, make sure you save this certificate on a trusted, secure machine only. Usually this is your production environment.

Run this on the server (not on your machine) as root.\
Replace your-domain.tld with the domain you request the certificate for and YYYY with the current year so you will not have any conflicts when requesting a certificate next year.

openssl req -new -sha256 -out www.your-dom...

Soft-scroll to an anchor with jQuery

This snippet makes links that refer to an anchor (like "<a href="#something">...</a>") scroll softly to it.\
In this example we only do it for links that also own a data-animate attribute.

$('a[href^="#"][data-animate]').live('click', function() {
  var hash = $(this).attr('href');
  var offset = $(hash).offset();
  if (offset) {
    $('html, body').animate({ scrollTop: offset.top }, 'slow');
    location.hash = hash;
    return false;
  }
});

Note that this could basically work for any element whos...

Defining host aliases in your SSH config

You probably already manage servers you often connect to inside the ~/.ssh/config file. What is nice: you may define alias names for hosts so that you can say something like ssh foobar-staging.

This is especially helpful for servers whose hostnames are hard to remember or who don't have a DNS record at all (and must be accessed via their IP address).

To achieve the above, you can define something like this in your ~/.ssh/config:

Host foobar-staging
  Hostname staging.example.com

Note that SSH will only match this for `ssh f...

How to employ and run your tests with parallel_tests to speed up test execution

When your cucumber features grow massively over time, the test execution can take a lot of time.
One easy way to speed up your test execution is to use the parallel_tests gem.
It comes along with some useful rake tasks that let you setup your local test environment shortly to run your features, specs or unit-tests in parallel.

Follow these steps to get it to work.

  1. Add the parallel_tests gem to your Gemfile test sections like that:

    # ./Gemfile
    
    group :development, :test do
    

...

Test that a number or money amount is shown with Cucumber

This is an awful way to test whether a number is shown on the screen:

Then I should see "5"

It is awful because the step above is green for 5, 5123 and -51.

This step definition below makes sure this doesn't happen. You can use it like this:

Then I should see the number 5

The step also works if you you'd like to test that the number is followed by a unit:

Then I should see the amount 5 €

The separator between the number and its unit is allowed to be either a space or a [nbsp](https://makandracards.com/makandra/838-generate...

Don't call #node on a Capybara element

Capybara allows you to select DOM elements, e.g. by using field, find_field(...) or field_labeled(...):

role_select = field_labeled('Role')

In the example above, role_select is now a Capybara::Driver::Node. You can call a number of methods on such a node, e. g. in order to click it or to make a selection on its descendants. These methods should be the same regardless of the driver Capybara is using (drivers are e.g. the headless Rack::Test or Selenium).

It i...

Cucumber steps to travel through time with Timecop

These steps are now part of Spreewald.


Here are some useful examples how to use the attached Cucumber Timecop steps:

When the date is 2011-05-06
When the time is 2011-05-06 17:30

There is also one really awesome step that lets you travel to the past or to the future:

When /^it is (\d+|a|some) (seconds?|minutes?|hours?|days?|months?|years?) (later|earlier)$/

As you can see, you describe the *time unit amo...

Fix randomly failing PDF cucumber tests

Sometimes PDF cucumber tests fail at the first test run and succeed at the second run. You can fix this with this step:

When PDF generation is ready
And I follow "Save as PDF"
# Checks for PDF contents go here

Here is the step definition:

When /^PDF generation is ready$/ do
  Then 'I should see ""'
end

Conditional comments for Internet Explorer with Haml

Internet Explorer 5+ is aware of conditional comments that let you target HTML for selected versions of IE. For example the HTML below would ask users of IE 6 and IE 7 to install Firefox:

<!--[if lt IE 8]>
  <a href='http://www.mozilla.com/en-US/firefox/'>Get a real browser</a>
<![endif]-->

You might wonder how to express such a conditional comment in your favorite templating language, Haml. You might even have converted a template back to ERB just for this ...

Split an array into columns

You know that you can collect an array as groups using in_groups or in_groups_of.

Maybe you want to fetch those values in "columns" where the first value lives in the first column, the second one in the second, etc. until it wraps, so that for example the fourth value is in the first of three columns.

Put the attached file into config/initializers/ to be able to say in_columns on any Array:

>> [1, 2, 3, 4, 5, 6, 7].in_columns(3)
=> [[1, 4, 7], [2, 5], [...

Bash script to run specs and features

Run rspec-and-cucumber from any project directory to run both RSpec and Cucumber. If available, rspec_spinner or cucumber_spinner are used.

Note that features are not run when specs fail.\
If you prefer to run them in parallel or run features regardless of the spec results, please adjust it for yourself accordingly.


This script is part of our geordi gem on github.

Validations on associated objects

Validations that need to access an associated object may lead to some trouble. Let's exemplify that using this example:

class Project < ActiveRecord::Base
   has_one :note
end

class Note < ActiveRecord::Base
   belongs_to :project
end

Now say we need a validation that ensures that a description is set (validates_presence_of :description) within Note but only if the Project has a flag called external set to true. The following code will lead to some problems as the associated object is not present when creatin...

Why preloading associations "randomly" uses joined tables or multiple queries

ActiveRecord gives you the :include option to load records and their associations in a fixed number of queries. This is called preloading or eager loading associations. By preloading associations you can prevent the n+1 query problem that slows down a many index view.

You might have noticed that using :include randomly seems to do one of the following:

  1. Execute one query per involved table with a condit...

Cast a string to the type of an ActiveRecord attribute

ActiveRecord models know how to cast a given string to the type of a given attribute (or column).

The following model will serve as our example:

create_table :notes do |t|
  t.string :title
  t.integer :user_id
  t.boolean :deleted
end

You can make the Note class cast strings into their respective types like this:

Note.columns_hash['user_id'].type_cast('123') # => 123
Note.columns_hash['deleted'].type_cast('1') # => true
Note.columns_hash['deleted'].type_cast('0') # => false

How to perform HTTP basic authentication in RSpec

The Basic Authentication header encodes username and password. Effectively, it's just Base64 plus a "Basic" prefix.
You can use ActionController::HttpAuthentication::Basic.encode_credentials for that, and put its result into the Authorization request header.

Request specs

For request specs, use the :header option.

it 'requires authentication' do
  get '/'
  expect(response.status).to eq(401)
end

it 'accepts valid credentials' do
  encoded_credentials = ActionController::HttpAuthentication::Basic.encode_credentials(use...