Andand and SimpleDelegator

The very useful andand gem does not play very nice with Ruby's SimpleDelegator (or vice versa).

This following will not work:

class MyDecorator < SimpleDelegator
  def foo
  end
end

MyDecorator.new(Object.new).andand.foo

The reasons are a bit subtle, basically SimpleDelegator will "force" some methods to be delegated, so the andand method is called on the wrapped object, not the delegator.

You can fix it like this:

class Decorator < SimpleDelegator
  def an...

Using sets for many-to-many relationships

A technique to vastly reduce the number of join model records that need to be stored in the database.

The technique is only effective when there is a high redundancy in your data, e.g. combinations of the same 20 tags are used to label thousands of books.

The technique is also limited in that your join models cannot have additional logic, such as attributes or callbacks.

Ther has-many-with-set gem is an implementation of this technique.

uninitialized constant MysqlCompat::MysqlRes (NameError)

If you get a stacktrace complaining about uninitialized constant MysqlCompat::MysqlRes a system library update might broke your gem.

You might have switched from MySQL to MariaDB, but forgot to rebuild your MySQL gems.

Try fully removing and re-installing the gem:

gem uninstall mysql mysql2
bundle install

Rubygems: Rebuild native extensions

Rarely, you might want to rebuild all gems with native extensions, because they might be compiled against outdated system libraries, resulting in some warnings or even segfaults or other ruby errors.

You can do that using

gem pristine --all

This will reset all gems to a pristine state as if you'd reinstall them, and as a side effect, rebuild all native extensions.

The above command will also help you sorting out errors like this after a distribution upgrade:

libmysqlclient_r.so.16: cannot open shared object file: No such fil...

Waiting for page loads and AJAX requests to finish with Capybara

If you're using the Capybara webdriver, steps sometimes fail because the browser hasn't finished loading the next page yet, or it still has a pending AJAX request. You'll often see workarounds like

When I wait for the page to load
Then ...

Workarounds like this do not work reliably, will result in flickering tests and should be avoided. There is no known reliable way to detect if the browser has finished loading the page.

Solution

Instead you should wait until you can observe the result of a page load. E.g. if y...

Advice: Reduce scopes with joins to simple IN-queries

In theory you can take any scope and extend it with additional joins or conditions. We call this chaining scopes.

In practice chaining becomes problematic when scope chains grow more complex. In particular having JOINs in your scope will reduce the scope's ability to be chained with additional JOINs without crashes or side effects. This is because ActiveRecord doesn't really "understand" your scope chain, it only mashes together strings that mostly happen to look like a MySQL query in the end.

**I don't generally advice against u...

floere/phony

The (admittedly crazy) goal of this Gem is to be able to format/split all phone numbers in the world.

Fixing errors with state_machine when excluding states

This is for you if you get the following strange error from the state_machine gem:

undefined method `-' for #<StateMachine::BlacklistMatcher:0x124769b0>

You probably did something like this in your state_machine ... do block:

def self.final_states
  [ :foo, :bar ]
end

transition (all - machine.final_states - [:baz]) => :target_state

Instead, define the source states like this:

def self.final_states
  [ :foo, :bar ]
end

transition (all - (mach...

Geordi: Running Selenium tests in a VNC buffer

Geordi now supports our solution for running Selenium tests without having Firefox or Chrome windows popping up all over your workspace.

This will stop Selenium windows from appearing on your desktop, but you can still inspect them when necessary.

Installation

Update geordi with gem install geordi.

Run geordi vnc --setup and follow the instructions.

Usage

geordi cucumber will automatically use VNC. Launchy will still open pages in the usual place.

geordi vnc will allow...

Workaround for broken integer division after requiring the mathn library

Ruby's mathn library changes Fixnum division to work with exact Rationals, so

2 / 3 => 0
2 / 3 * 3  => 0

require 'mathn'
2 / 3 => Rational(2,3)
2 / 3 * 3 => 2

While this might sometimes be quite neat, it's a nightmare if this gets required by some gem that suddenly redefines integer division across your whole project. Known culprits are the otherwise excellent distribution and [GetText](https://g...

Get rid of WARNING: Nokogiri was built against LibXML version 2.7.7, but has dynamically loaded 2.7.8

If you get this warning on your local machine one of these steps might help:

Rebuilt the gem with the newer library

gem install --no-rdoc --no-ri nokogiri -- --with-xml2-include=/opt/local/include/libxml2 --with-xml2-lib=/opt/local/lib

If you still get the error, try to uninstall all nokogiri versions with

gem uninstall nokogiri

and install nokogiri again.

Fixing the issue on servers

However, on our servers this probably will not work. On the server, gems are stored in the ../shared/bundle/ruby/:version/gems dire...

Asset pipeline may break Javascript for IE (but only on production)

If some of your JavaScripts fail on Internet Explorer, but only in staging or production environments, chances are that JavaScript compression is the culprit.

By default, Rails 3.2 compresses JavaScript with UglifyJS. I have seen a few cases where this actually breaks functioning JavaScript on IE (one example is the CKEditor).

I fixed this by switching to Yahoo's YUI Compressor.

To do this, do the following:

  • replace the uglifier gem with the yui-compressor gem...

Migrating to Spreewald

This describes how to migrate an existing cucumber test suite to Spreewald.

  1. Add the gem

  2. Include spreewald into your cucumber environment by putting
    require 'spreewald/web_steps'
    require 'spreewald/email_steps'
    # ...
    or just
    require 'spreewald/all_steps'
    into your support/env.rb.

  3. Look through your step definitions for everything that might be included in Spreewald. Candidates are web_steps, shared_steps, table_steps, `em...

Spreewald: Old-school cucumber steps, freshly pickled

Cucumber_rails' old-school web-steps have been deprecated for a while, urging developers to write high-level step definitions that directly use Capybara or Webrat.

We think that's a bit drastic. More high-level steps are good, but ticking the odd check box with a general step is not always bad.

So we took the old web steps, improved them a bit, added some other favorites of ours (steps for emails, tables, [time travelling](/ma...

How to not leave trailing whitespace (using your editor or Git)

There is no reason to leave trailing whitespace characters in your project's files, so don't add any.

A git diff --check will tell you if there are any and you should not commit when you see them. So go ahead and switch your editor/IDE to automatically remove them for you.
Below are a few instructions on how to get them removed by your favorite IDE or editor.

Note that except for RubyMine, the following changes will remove trailing white-space on all lines, not only those that you changed.
While this should not be a problem if your proje...

ActionMailer sometimes breaks e-mails with multiple recipients in Rails 2

The ActionMailer in Rails 2 depends on a buggy version of TMail, which sometimes inserts a blank line into the mail header when sending a mail to multiple recipients. This makes the header end prematurely.

The reason why this is not exploding in your face all the time is that when you are relaying your e-mail through an MTA like Exim, it will fix this for you.

Fix for Rails if you don't have an awesome MTA

TMail is no longer maintained. The bug is fixed...

Create autocompletion dropdown for Cucumber paths in Textmate

Ever wanted autocompletion for paths from paths.rb in Cucumber? This card lets you write your steps like this:

When I go to path *press tab now* # path is replaced with a list of all known Cucumber paths

This is how you do it

(key shortcuts apply for TextMate2)

  1. Open the bundle editor (ctrl + alt +  + B)

  2. Create a new Item ( + N), select "Command"

  3. Paste this:
    ^
    #!/usr/bin/env ruby -wKU
    require File.join(ENV['TM_SUPPORT_PATH'], 'lib', 'ui.rb')

    cucumber_paths = File.join ENV['TM_PROJECT_DIRECTORY'], 'features'...

Fix error: Invalid gemspec / Illformed requirement

When you get an error like this:

Invalid gemspec in [/opt/www/foo-project.makandra.de/shared/bundle/ruby/1.8/specifications/carrierwave-0.6.2.gemspec]: Illformed requirement ["#<YAML::Syck::DefaultKey:0x7fda6f84d2e8> 1.1.4"]

... the machine's Rubygems needs to be updated.

If that happens on your local machine

  • Manually remove the offending's gem files and specifications. The paths will be something like /usr/lib/ruby/gems/1.8/gems/your-broken-gem and `/usr/lib/ruby/gems/1.8/specificatio...

Paperclip: Move attachements from local storage to AWS S3

We frequently use the handy Paperclip Gem to manage file attachments.

If you need to move the files from local storage (i.e., your servers' harddisk) to Amazon S3, you can simply change settings for Paperclip to use the S3 storage adapter and use this script to migrate to S3. Put the snippet into a chore if you don't want to run that in the console.
YOUR_LOCAL_STORAGE_MODEL_DIRECTORY should be something like 'storage/your_model'.

Dir.glob(YOUR_LOCAL_STORAGE_MODEL_DIRECTORY**/*).each do |path|...

How to fix gsub on SafeBuffer objects

If you have an html_safe string, you won't be able to call gsub with a block and match reference variables like $1. They will be nil inside the block where you define replacements (as you already know).

This issue applies to both Rails 2 (with rails_xss) as well as Rails 3 applications.

Here is a fix to SafeBuffer#gsub. Note that it will only fix the $1 behavior, not give you a safe string in the end (see below).

Example

def test(input)...

MySQL: Can I speed up LIKE queries by adding an index?

For string columns, MySQL indexes the left side of a string. That means an index can speed a like query that has a wildcard on the right side:

SELECT * FROM foo WHERE field LIKE "bar%" # will be faster with an index

It can not speed up a query that has a variable left side:

SELECT * FROM foo WHERE field LIKE "%bar%" # will not be faster with an index

That also means if you use the ancestry gem you should index your ancestry column if you use scopes like descendants or `su...

Mock the browser time or time zone in Selenium features

In Selenium features the server and client are running in separate processes. Therefore, when mocking time with a tool like Timecop, the browser controlled by Selenium will still see the unmocked system time.

timemachine.js allows you to mock the client's time by monkey-patching into Javascript core classes. We use timemachine.js in combination with the Timecop gem to synchronize the local browser time to the ...

Silencing Your Staging Environment - The Hashrocket Blog

Testing with real live production data does come with at least one catch. All those real live users in your production environment have real live email addresses that receive real live emails.

The post includes monkey patch for ActionMailer that rewrites the domain of all recipients. It's a different take on the problem than our own mail_magnet gem.