Prevent SSH from timing out

If you have problems with SSH session timing out, add the following to your /etc/.ssh/config:

Host *
  ServerAliveInterval 55
  ServerAliveCountMax 2

Using the full power of have_css

Capybara's has_css? matcher has a couple of options you might find useful.

Check that a selector appears a given number of times

Use the :count option like this:

Then /^I should see (\d+) users?$/ do |count|
  page.should have_css('ul#users li', :count => count.to_i)
end

Check that a selector has a given text content

Use the :text option like this:

Then /^I should see a user with name "([^\"]*)"$/ do |nam...

Even with bundler your gem order can be significant

Even when you're using bundler, it might be significant in which order your gems are listed in your Gemfile. This can happen when gems are running around calling require or require_dependency on other gems or application classes when loaded (don't do that!).

A known culprit of this is the (otherwise wonderful) resource_controller gem, which requires ApplicationController when loaded. When your ApplicationController requires later-loaded gems when loaded, Rails will not boot.

He...

Inline if-then-else in MySQL queries

It can be useful to have a Ruby expression like condition ? positive_case : negative_case in MySQL queries:

UPDATE users SET monthly_debit = IF(subscriber, 19, 0)

Generate a strong secret from the shell

A good tool to generate strong passwords and secrets is "apg". You can get it with

sudo apt-get install apg

To create a strong secret for sessions, hashed Paperclip paths, etc. say

apg -m128 -a1 -E\'\"

Arguments explained:

  • The -m parameter defines the secret length
  • -a1 makes apg choose from all 7-bit ASCII characters instead of just the alphabet
  • -E\'\" excludes quote characters so you can easily paste the secret into a Ru...

Taking advantage of RSpec's "let" in before blocks

Inside before :each blocks you can refer to variables that you introduce via let later on.

They do not need to be defined ahead of your before block and can be different for individual sections.

It works just like that:

describe User do
  describe '#locked?' do
    
    before :each do
      subject.should_receive(:current_plan).and_return plan
    end
    
    context 'when expiring today' do
      let(:plan) { stub(:expiry => Date.today) }
      it 'should be false' do
        subject....

Install the Paperclip gem on Ubuntu servers

You need to install the following packages before you can build the Paperclip gem:

sudo apt-get install imagemagick librmagick-ruby

Pay attention to the order of your submit buttons

If you have several submit elements (inputs or buttons with type="submit") that each cause different things to happen (e.g. you might have a button that sends an extra attribute) you might run into trouble when submitting the form by pressing the return key in a field.

When nothing fancy like a tabindex is defined it seems as if the first submit element inside a form is chosen (and has its attributes submitted) when pressing return.\
So, if possible, put your "default" (aka least harmful) submit element before others.

NB: If you s...

Using state_machine events within a resource_controller

If you need to call a state_machine event and do not want to re-define resource_controller's create method, try this:

create.before do
  object.state_event = :launch_spaceship
end

Kill a dead SSH shell

If a SSH shell dies (from timeout for example), you cannot kill it with the usual CTRL-C or CTRL-Z. Instead, press
[ENTER]~.
(That is ENTER TILDE PERIOD).

Sun Java JVM/JRE on Ubuntu Linux

Note that you should disable the Java plug-in in your browsers after installation.

Ubuntu >= 12.04

Java 11

sudo apt install openjdk-11-jre-headless

Java 10

sudo add-apt-repository ppa:linuxuprising/java
sudo apt-get update
sudo apt-get install oracle-java10-installer

Java 8

You probably want to get rid of OpenJDK (which is installed by default and leads to bad RubyMine performance):

...

Reload the page in your Cucumber features

Both these approaches will keep your GET parameters -- and will only work for GET requests.

  • Capybara:

    When /^I reload the page$/ do
      visit [ current_path, page.driver.request.env['QUERY_STRING'] ].reject(&:blank?).join('?')
    end
    
  • Webrat:

    When /^I reload the page$/ do
      visit url_for(request.params)
    end
    

For a step that distinguishes between drivers (Selenium, Rack::Test, Culerity), check [n4k3d.com](http://n4k3d.com/blog/2011/02/02/reloading-the-page-in-cucumber-with-capybara-and-seleniu...

Replace substrings in Cucumber step argument transforms

Cucumber step argument transforms can be a powerful way to make your steps more flexible.

Note however that if your transform only matches a substring (no ^ and $ markers at the beginning and end), you are still expected to return a replacement for the whole string that was piped through the transform. If you don't do that, you will truncate that string and possibly make the calling step match where it should not.

Let's say you want a transform that replaces subs...

RSpec's context method is broken

RSpec's context (which is basically an alias for describe) takes over your whole application. No object may have its own context method, or you will always receive errors like

"No description supplied for example group declared on ~/project/app/..."

The easiest workarounds:

  • do not name any method context
  • use describe instead of context in your specs, and put this into your spec_helper.rb:\
    Spec::DSL::Main.class_eval do
    if method_defined? :context
    undef :context
    end
    end

Places where cron jobs can hide

  1. In /etc/crontab
  2. In /etc/cron.d/*
  3. In /etc/cron.hourly/*
  4. In /etc/cron.daily/*
  5. In /etc/cron.weekly/*
  6. In /etc/cron.monthly/*
  7. In the personal crontab of any user. This is a magic file you can view with crontab -l and edit with crontab -e. You'll need to su to the respective user to view or edit her crontab.

Delete from joined MySQL tables

When you need to delete rows from a table, and the delete conditions require a joined table, MySQL needs to know which table you want to delete from.

Let's say that Post belongs_to :author. In order to delete all posts from the author named "Eric", write

DELETE posts FROM posts LEFT JOIN authors ON posts.author_id = authors.id WHERE authors.name = 'Eric'

Notice the additional "posts" between DELETE and FROM.

Save ActiveRecord models without callbacks or validations (in Rails 2 and Rails 3)

Rails 2

You can use

record.send(:update_without_callbacks)

or

record.send(:create_without_callbacks)

This can be used as a lightweight alternative to machinist's make or FactoryGirl's create, when you just need objects in the database but don't care about any callbacks or validations. Note that create_without_callbacks does not return the object, so you might want to do

record = Record.new.tap(&:create_without_callbacks)

Rails 3

Rails 3 no longer comes with update_without_callbacks or `crea...

Fix permissions of temporary RTeX files (which are group and world-readable)

We use RTeX for PDF exports.
While converting LaTeX to PDF, RTeX opens a temporary file which has problematic permissions: Both group and world can read those files.

Although the temp files should go away they sometimes live longer than one would expect.
We patched RTeX to fix this (and have more secure permissions). Place the code below into config/initializers/rtex.rb