Manipulate an array attribute using multiple check boxes

E.g. when you're using a tagging gem, you have seen virtual attributes that get and set a string array:

post = Post.last
puts post.tag_list # ['foo', 'bar', 'baz']
post.tag_list = ['bam']
puts post.tag_list # ['bam']

If you would like to create a form displaying one check box per tag, you can do this:

- form_for @post do |form|
  = form.check_box :tag_list, { :multiple => true }, 'foo', nil
  = form.check_box :tag_list, { :multiple => true }, 'bar', nil
  =...

Use the back button in Cucumber

In order to go back one page in your Cucumber tests, you can use the following step definition for Capybara:

When(/^I go back$/) do
  visit page.driver.request.env['HTTP_REFERER']
end

If you're on Webrat, this should work:

When(/^I go back$/) do
  visit request.env["HTTP_REFERER"])
end

An improved version of this step is now part of our gem spreewald on Github.

Test a gem in multiple versions of Rails

Plugins (and gems) are typically tested using a complete sample rails application that lives in the spec folder of the plugin. If your gem is supposed to work with multiple versions of Rails, you might want to use to separate apps - one for each rails version.

For best practice examples that give you full coverage with minimal repitition of code, check out our gems has_defaults and assignable_values. In particular, take a look at:

  • Multiple `sp...

Install a specific version of a gem

To install webmock 1.5.0:

sudo gem install webmock --version "=1.5.0"

or
sudo gem install webmock -v "=1.5.0"

Prevent Bundler from downloading the internet

As a user of Bundler you have spent significant time looking at this message:

Fetching source index for http://rubygems.org/

To make Bundler skip this index update and only use installed gems, you can use the --local option:

bundle install --local

Unfortunately this does not work with bundle update.

It is said that Bundler 1.1 will use a feature of Rubygems.org that allows partial index updates. Hopefully the wh...

Generate a Unicode nonbreaking space in Ruby

Regular spaces and non-breaking spaces are hard to distinguish for a human.
Instead of using the   HTML entity or code like " " # this is an nbsp, use a well-named helper method instead.

def nbsp
  [160].pack('U*')
end

160 is the ASCII character code of a non-breaking space.

Defining and using sub-classes with modularity

Given this class:

class Foo
  class Bar
  end
end

If you want to clean up this code with the modularity gem, you might try something like this:

class Foo
  does 'bar'
end

module BarTrait
  as_trait do
    class Bar
    end
  end
end

Note that this changes Bar's full class name from Foo::Bar to BarTrait::Bar. If you have methods inside Foo (or other classes), you would have to change all references accordingly, which is quite unpleasant.

You can solve it like that:
`...

Install gems for all bundled projects

This is a bash script for those of you who need to install all gems for all projects (e.g. to get started quickly on a newly installed system).

Put it into your ~/bin/ and run it from the directory that holds your projects.

Note that, like the vanilla bundle install, this will fail whenever a new gem compiles native components and requires a missing system dependency.

Terminus: a client-side Capybara driver

Terminus is a Capybara driver where most of the driver functions are implemented in client-side JavaScript. It lets you script any browser on any machine using the Capybara API, without any browser plugins or extensions.

Standalone Cucumber Test Suite

Sometimes you inherit a non Rails or non Rack based web app such as PHP, Perl, Java / JEE, etc. I like using cucumber for functional testing so I put together this project structure to use as a starting point for testing non Ruby web based applications.

Fix LoadError with Rails 3 applications on Passenger

After switching to Rails 3 you may get a LoadError with the following message when trying to use your application via passenger:
no such file to load -- dispatcher

Your Passenger version is most likely out of date.

Update the gem, then install the apache module again:
sudo gem install passenger
sudo passenger-install-apache2-module

Follow any instructions. Update your /etc/apache2/httpd.conf with the lines given at the end of the installation process to use the version you just installed.

Migrating to RSpec 2 from RSpec 1

You will need to upgrade to RSpec >= 2 and rspec-rails >= 2 for Rails 3. Here are some hints to get started:

  • In RSpec 2 the executable is rspec, not spec.
  • RSpec and rspec-rails have been completely refactored internally. All RSpec classes have been renamed from Spec::Something to RSpec::Something. This also means that every require 'spec/something' must now be require 'rspec/something'.
  • In spec_helper.rb, Spec::Runner.configure becomes RSpec.configure
  • It has become really hard to extend specific example groups ...

Shell script to quickly switch Apache sites

I prefer the application that I'm currently working on to be reachable at http://localhost/.

So when I switch to another project, I use this handy shell script to set one site as the current one. Call it just like this:
apache-site makandra-com

Note that it disables all other sites in your Apache configuration so you would not want to use this on production machines.
Furthermore it will also enable the default site if that was available.

When you call apache-site with no arguments, it will list all available sites.


...

On memoizing methods that return a scope

Be careful when memoizing a method that returns a scope, e.g.:

def variants
  scoped(:conditions => { :name => name })
end

memoize :variants

Because of the way memoize is implemented, that method now no longer returns a scope but its loaded target array.

The best solution is to use the Memoizer gem instead.

A workaround is to roll your own memoization:

def variants
  @va...

Working around the ancestry gem's way of object destruction

The ancestry gem allows you to easily use tree structures in your Rails application.

There is one somewhat unobvious pitfall to it: its way of applying the orphan_strategy which defines how it handles children of an object going to be destroyed.

What's this all about?

In many cases you might want to disallow destruction if there are any child nodes present. The restrict strategy does the trick but raises an exception when destroy is called:
has_ancestry :orphan_st...

Install the Nokogiri gem on Ubuntu servers

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

sudo apt-get install libxml2-dev libxslt1-dev

Resolve Aspell errors with your Rails application

If you get an error message like that you are missing the Aspell files a specific language:

No word lists can be found for the language "de"

Solve it by installing the proper package, e.g. on Ubuntu:

sudo apt-get install aspell-de

apotonick's hooks at master - GitHub

Hooks lets you define hooks declaratively in your ruby class. You can add callbacks to your hook, which will be run as soon as you run the hook.

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

An obscure kernel feature to get more info about dying processes

This post will describe how I stumbled upon a code path in the Linux kernel which allows external programs to be launched when a core dump is about to happen. I provide a link to a short and ugly Ruby script which captures a faulting process, runs gdb to get a backtrace (and other information), captures the core dump, and then generates a notification email.

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)

Precedence of Ruby operators

  1. [ ] [ ]=
  2. **
  3. ! ~ + -
  4. * / %
  5. + -
  6. >> <<
  7. &
  8. ^ |
  9. <= < > >=
  10. <=> == === != =~ !~
  11. &&
  12. ||
  13. .. ...
  14. ? :
  15. = %= { /= -= += |= &= >>= <<= *= &&= ||= **=
  16. defined?
  17. not
  18. or and
  19. if unless while until
  20. begin/end

For more information see Table 18.4 in The Pragmatic Programmer's Guide.

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

jsmestad's pivotal-tracker at master - GitHub

Ruby gem that provides an AR-style interface for the Pivotal Tracker API.