New Firefox and gem versions for our Selenium testing environment (Ubuntu 14.04+)

Firefox 5.0.1, which we were using for most Rails 2.3 projects, does not run on Ubuntu 14.04 any more. Here is how to update affected projects.

  1. Update (or create) .firefox-version with the content: 24.0
    If you haven't installed Firefox 24 yet, the next time you run tests with Geordi, it will tell you how to install it.

  2. On a Rails 2 project:

Pimp my IRB

Put the attached files into your home directory and enjoy.

.irbrc

  • defines interesting_methods, which is essentially all methods without top-level methods inherited from Object/Module
  • requires awesome_print, if present
  • requires interactive_editor, if present (basically makes vim available)
  • loads .irbrc_rails if in Rails (e.g. for the Rails console)

.irbrc_rails

  • defines efind(email), which is a shortcut to find users by email
    ...

HTML emails with inline stylesheets and webpacker

Many mail clients do not support external style sheets. Some even require all styling inline, which means you'll have to do your styling inline. For Rails applications, you can use Roadie or premailer, which lets you keep your well-structured CSS files and do the inlining for you.

See Designing HTML email

Since Roadie is now in passive maintenance mode, we go with premailer:

Include premailer in your Gemfile:

gem 'premailer-ra...

Fix „command failed: /usr/bin/wkhtmltopdf ...“ using PDFKit middleware

Ubuntu 12.04 LTS x64, Ruby 1.8.7, Rails 2.13, PDFKit 0.5.4, Phusion Passenger Apache 2

I ran into this, when I started using passenger to deal with the Single Thread Issue which caused my webrick to deadlock when an ActionController::RoutingError (No route matches "...") occurred.

These steps brought me a little further

(1) assert dependencies are installed

 sudo aptitude install openssl build-essential xorg libssl-dev

(2) only for 64bits OS Run one by one the follo...

Fix Rubygems warning: Gem.source_index is deprecated, use Specification

After updating Rubygems you see a wall of deprecation warnings like this:

NOTE: Gem::SourceIndex#add_spec is deprecated, use Specification.add_spec. It will be removed on or after 2011-11-01.
Gem::SourceIndex#add_spec called from /usr/local/lib/site_ruby/1.8/rubygems/source_index.rb:197.

NOTE: Gem::SourceIndex#add_specs is deprecated with no replacement. It will be removed on or after 2011-11-01.
Gem::SourceIndex#spec_dirs= called from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.14/lib/bundler/rubygems_integration.rb:175

...

How to use Haml in your helpers

You know those helper methods that just render some HTML but look weird because of content_tags all over the place? You could also use Haml instead.

Example

Consider the following helper.

def greeting
  message = ''.html_safe
  message << 'Welcome to '
  message << content_tag(:span, Rails.env, class: 'greeting--location')
  content_tag :div, message, class: 'greeting'
end

That looks clumsy and is hard to read.

Wouldn't it be nicer to say something like this?

def greeting
  render_haml <<-HAML
 ...

Split an array into groups

Given group size

If you would like to split a Ruby array into pairs of two, you can use the Rails ActiveSupport method in_groups_of:

>> [1, 2, 3, 4].in_groups_of(2)
=> [[1, 2], [3, 4]]

>> [1, 2, 3, 4, 5].in_groups_of(2)
=> [[1, 2], [3, 4], [5, nil]]

>> [1, 2, 3, 4, 5].in_groups_of(2, 'abc')
=> [[1, 2], [3, 4], [5, 'abc']]

>> [1, 2, 3, 4, 5].in_groups_of(2, false)
=> [[1, 2], [3, 4], [5]]

Given group cou...

Use a Bash function to alias the rake command to Spring binstubs or "bundle exec" fallback

There are different ways to run rake:

  • On Rails 4.1+ projects, you have Spring and its binstubs which dramatically improve boot-up time for Rake and similar. You need to run bin/rake to use them.
  • On older projects, you want to run "bundle exec rake" to avoid those ugly "already activated rake x.y.z" errors that hit you when different rake versions are installed for your current Ruby.

Here is a solution that gives you a plain rake command which uses a binstubbed bin/rake if available and falls back to bundle exec rake if necessar...

SSHKit 1.9.0 failure for Capistrano deploy

SSHKit 1.9.0 might fail with the following error, when trying to deploy a Rail application. Upgrading the gem to version 1.21.0 fixed the issue.

Traceback (most recent call last):
	17: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9.0/lib/sshkit/runners/parallel.rb:12:in `block (2 levels) in execute'
	16: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9.0/lib/sshkit/backends/abstract.rb:29:in `run'
	15: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9....

Open a MySQL shell using credentials from database.yml

In order to open a MySQL shell without the need to enter user and password, you can say the following in any Rails 2 project:

script/dbconsole -p

In Rails 3 you can say:

rails dbconsole -p

If you'd like to enter a database for an environment other than development you can say:

script/dbconsole -p staging

Minified JavaScript and CSS

JavaScripts and CSS should be minified for production use.

In Rails 3.1+ the asset pipeline will take care of this. Thus you're best off using an uncompressed version of your Javascript in development. Also load the non-minified versions of libraries. This way debugging will be easier and you will still get all the minification love once deployed.

In Rails 2.3 and 3.0 you should at least embed external JavaScript libraries in minified form, using something like JavaScript compressor.

Edge Rider: Power tools for ActiveRecord scopes

In our continued quest to extract proven code snippets from makandropedia into tested and upgradable gems, we have released Edge Rider.

Edge Rider was created with two intents:

  1. Provides a number of utility methods to facilitate hardcore work with scopes.
  2. Provide a stable API for working with scopes across multiple versions of Rails, since Rails has a tradition of breaking details of its scope API every other release.

The gem bundles multiple patches and initializers we've been using for hard...

Postgres: How to force database sessions to terminate

If another session is accessing your database you are trying to reset or drop you might have seen the following error:

PG::ObjectInUse: ERROR:  database "foo_development" is being accessed by other users
DETAIL:  There is 1 other session using the database.

This could be the rails server, rubymine and many more. Beside terminating the session connection manually you can also find out the pid and kill the process.

1. rails db
2. SELECT * FROM pg_stat_activity;

datid            | 98359
datname          | foo_developm...

NoMethodError: undefined method `cache' for Gem:Module

I got this error when running Rails 2.3 tests for Rails LTS. More stacktrace:

NoMethodError: undefined method `cache' for Gem:Module
    /vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:212:in `each'
    /vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:146:in `to_a'
    /vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:146:in `cache'
    /opt/vagrant_ruby/lib/ruby/1.8/fileutils.rb:243:in `inject'
    /vagrant/rails-2-3-lts-repository/railties/l...

Stub a request's IP address in a Cucumber scenario

The solution in this card is based on a stack overflow post by Leventix.

If you need to make request come from a fixed IP address for the duration of a Cucumber scenario, the code below lets you write this:

Given my IP address is 188.174.117.205

Rails 3

Given /^my IP address is "(.*?)"$/ do |ip|
  ActionDispatch::Request.any_instance.stub(:remote_ip).and_return(ip)
end

Rails 2
-----...

How to fix: "rake db:rollback" does not work

When you run rake db:rollback and nothing happens, you are probably missing the latest migration file (or have not migrated yet).

$ rake db:rollback
$ 

If that happens to you, check your migration status.

$ rake db:migrate:status
   up     20160503143434  Create users
   up     20160506134137  Create pages
   up     20160517112656  Migrate pages to page versions
   up     20160518112023  ********** NO FILE **********

When you tell Rails to roll back, it tries to roll back the latest change that was mi...

How to silence "I18n.enforce_available_locales" deprecation warnings

Before Rails 3.2.14, when supplying an invalid locale to I18n, it would fall back to its config.i18n.default_locale (which is :en by default). Eventually, this will be changed to raise an error by default -- for now, it shows a deprecation warning.

Since Rails 3.2.14 and 3.2.15 did not include security updates, you might not have applied them and probably now encounter these deprecation warnings after upgrading to 3.2.16 (or 4.0.2):

[deprecated] I...

Enable CSRF protection in Javascript tests

You might not know that Rails disables CSRF protection in tests. This means that if you accidentally forget to send the CSRF token for non-GET requests, your tests will be green even though your application is completely broken (a failed CSRF check usually logs out the user). Rails probably does this because CSRF protection sort of requires Javascript.

You want to enable CSRF protection in Cucumber scenarios that can speak Javascript. To do so, copy the a...

When Sass-generated stylesheets print a Encoding::CompatibilityError

We upgraded a Rails 2 application to Rails 3.2 and Ruby 2.1, changed the mysql adapter from mysql to mysql2, but did not activitate the asset pipeline. Instead we used Sass the old-school way (stylesheets in public/sass/*.sass) and relied on stylesheet_link_tag to activate the Sass compiler.

Now all Sass-generated stylesheets inserted the following text into body:before:

Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT

I could get rid of this by removing all generated .css files in `...

MySQL: Do not use "WHERE id IN (SELECT ....)"

Note: This applies specifically to MySQL. In PostgreSQL for example, this is not an issue.

If you care about performance, never use a query like

UPDATE users SET has_message = 1 WHERE users.id IN (SELECT user_id FROM messages)

MySQL does not optimize this and seems to scan the temporary table, which isn't indexed, for every row in the update statement. This applies to other statements than UPDATE as well.

Instead, either use a JOIN like

UPDATE users INNER JOIN messages ON messages.user_id = users.id SET has_message =...

Fix: "undefined method `bytesize' for #<Array>"

I believe that when WEBrick has trouble bringing up your Rails application, the WEBrick component that is supposed to print you a pretty error message has a bug and sometimes fails with this message:

"undefined method `bytesize' for #<Array>"

Starting the application in Passenger gave me a stacktrace in log/development.log that pointed to the actual problem.

Possible causes discovered by looking at the logs
-----------------------------------------------------...

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...

Aggregated RSpec/Cucumber test coverage with RCov

With defaults, RCov doesn't work the way you how you would like it to. To create a nice test coverage report, copy the attached file to lib/tasks/rcov.rake. After that rake rcov:all will run all RSpec examples and Cucumber features. The report will be written RAILS_ROOT/coverage/index.html.

Here is what the task does in detail:

  • Generates aggregated coverage of both RSpec and Cucumber
  • Works with Rails 2 and Rails 3
  • Reports for app/**/*.rb and nothing else
  • If called with an environment variable IGNORE_SHARED_TRAITS=true it ...

Using StaticMatic for static pages

Update: Staticmatic will not be further developed. They suggest to switch to middleman.


If you need to make a static web page and find yourself missing all your Rails comforts, take a look at StaticMatic.

This works like an extremely stripped down version of Rails, giving you

  • HAML
  • SASS
  • helpers
  • partials

When done, everything is simply compiled to s...