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

Execution of shell code in Ruby scripts

Deprecated ways to execute shell code in Ruby

This is just a reference for legacy code. For new code, always use capture3.

%x{ } or backticks – quick and easy

Returns the standard output of running the given command in a subshell. This is an alias for `...`, and you can use string interpolation.

Example:

name = 'ls'
result = `which #{name}`

It does not escape anything you inject in the string, so be aware of possible security vulnerabilities...

Sudo a gem executable does not work on Ubuntu

Today I needed to execute a ruby gem executable with sudo. But, surprisingly, bash would tell me command not found for the gem that ran lovely without sudo.

Gem bins are installed to /var/lib/gems/1.8/bin, which is not in sudo’s PATH. Unfortunately, you can’t change the path, since sudo for Ubuntu is compiled with the --with-secure-path option.

#Solution A: symlink the gems (if you need only some few gems)

  • for each gem you need for sudo, run `ln -s /var/lib/gems/1.8/bin/gem_for_sudo /usr/local/bin/gem_for_sudo

#Soluti...

Putting static content on Cloudfront

We recently decided to put static content for HouseTrip.com to Amazon Cloudfront for a faster user experience. This happens fully automatically on deploy and is transparent in development. Together with a heavy use of sprites this sped up page load time quite nicely.

These are a couple of the problems you need to solve in order to do this:

  • There is no good way to invalidate Cloudfront cached assets, and Cloudfront will ignor...

Capistrano 2: Which Capistrano hooks to use for events to happen on both "cap deploy" and "cap deploy:migrations"

When deploying an application with "cap deploy" by default [1] you only deploy your code but do not run migrations. To avoid an application to be running with code which requires database changes that did not happen yet you should use cap deploy:migrations.

The problem

Let's say that you have something like that in your config/deploy.rb to create a database dump every time you deploy:
before 'deploy', 'db:dump'
This will not be called for cap deploy:migrations. The same applies to other things that are hooked s...

Why a Rails flash message is shown twice

You set a flash message and it shows up as it should. However, it is displayed again the next time you follow a link. Here is why:

You have to differentiate between a render and a redirect_to because a flash message is only deleted after a redirect. If you want a message to be seen in the next request after a redirect, use flash[]. If you want a message to be seen in the current request, use flash.now[].

Workaround for the lazy

If you cannot be bothered to decide which flash hash to use, or if the fl...

How to send HTTP requests using cURL

  • Reading a URL via GET:

    curl http://example.com/
    
  • Defining any HTTP method (like POST or PUT):

    curl http://example.com/users/1 -XPUT
    
  • Sending data with a request:

    curl http://example.com/users -d"first_name=Bruce&last_name=Wayne"
    

    If you use -d and do not set an HTTP request method it automatically defaults to POST.

  • Performing basic authentication:

    curl http://user:password@example.com/users/1
    
  • All together now:

    curl http://user:password@example.com/users/1 -XPUT -d"screen_name=batman"
    

...

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

Installing RMagick on Ubuntu

When installing RMagick you may get an error messages like this:

Version 2.13.1:

checking for Ruby version >= 1.8.5... yes
checking for gcc... yes
checking for Magick-config... no
Can't install RMagick 2.13.1. Can't find Magick-config in /home/arne/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/var/lib/gems/1.8/bin

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
d...

Opera 11: Show full address, including GET parameters

By default, Opera 11 hides any passed params and the URL's protocol until you focus the address bar.

To disable hiding URL parameters, open up Tools → Preferences (Ctrl+F12) → Advanced → Browsing and check "Show full web address in address field". No need to touch opera:config.

The badge that displays the page's "zone" (Web, Secure, Opera, ...) will be shrinked so you can still see a yellow lock for proper SSL connections, etc.

wycats/artifice

Artifice allows you to replace the Net::HTTP subsystem of Ruby with an equivalent that routes all requests to a Rack application.

You can use Sinatra, raw Rack, or even Rails as your application, allowing you to build up an equivalent to the remote service you are mocking out using familiar and convenient tools to route requests and build up responses.

Cancelling event propagation

Within an event handler, there are multiple methods to cancel event propagation, each with different semantics.

  • event.preventDefault()

    Only prevents the default browser behavior for the click, i.e. going to a different url or submitting a form.

    When invoked on a touchstart event, this also prevents mouse events like click to be triggered.

  • event.stopPropagation()

    Prevents the event from bubbling up the DOM.

  • `event.st...

Caching in Rails

The information in this card is only relevant for Rails 2.3-era apps.


This note gives a quick introduction into caching methods (page caching, action caching and fragment caching) in rails and describes some specific problems and solutions.

The descriptions below are valid for Rails 2 and 3. Recently, caching with timestamp- or content-based keys has become more popular which saves you the pain of invalidating stale caches.

How to enable/disable caching

To enable or disable caching in rails you ca...

Upgrading Cucumber and Capybara to the latest versions available for Rails 2

Specify these gem versions in your Gemfile:

gem 'cucumber', '~> 1.3.0'
gem 'cucumber-rails', '= 0.3.2' # max version for Rails 2
gem 'capybara', '< 2' # capybara 2+ requires Rails 3
gem 'mime-types', '< 2' # dependeny of capybara
gem 'nokogiri', '< 1.6' # dependency of capybara
gem 'rubyzip', '< 1' # dependency of selenium-webdriver, rubyzip 1+ requires Ruby 1.9
gem 'cucumber_factory'
gem 'database_cleaner', '< 1'
gem 'cucumber_spinner', '~> 0.2.5'
gem 'launchy', '~> 2.1.2'

With these versions set, `...

state_machine 0.10.0 was released

Now allows to list transition paths from and to arbitrary states.

Ruby and Rails deprecation warnings and how to fix them

Add deprecation warnings and their solution or link to available solutions.

Global access to Rake DSL methods is deprecated. Please include Rake::DSL into classes and modules which use the Rake DSL methods.

Open your Rakefile and add the following line above YourApp::Application.load_tasks:

YourApp::Application.class_eval do
  include Rake::DSL
end

Use of ole/file_system is deprecated. Use ole/storage (the file_system api is recommended and enabled by default)...

Sanitize user-generated filenames and only send files inside a given directory

If in your application your users pass along params that result in filenames, like invoices/generated?number=123. This could be your (very careless) controller method:

def generated
  send_file File.join(Rails.root, 'shared', 'invoices', params[:number])
end

This allows your users not only to access those files but also any files your application can read, like this:

invoices/generated?number=../../../../../etc/passwd
# => send_file '/etc/passwd'

You do not want this. In most cases you should prefer a show met...

CSS3 Pie: Element not properly redrawn

Pie sometimes does not properly redraw elements upon changes. This often happens when the change comes from somewhere further up the DOM.

Consider something like:

<ul>
  <li class="active"><div class="content">Active element</div></li>
  <li class="inactive"><div class="content">Inactive element</div></li>
</ul>

with CSS
li .content {
-webkit-box-shadow: #666 0px 2px 3px;
-moz-box-shadow: #666 0px 2px 3px;
box-shadow: #666 0px 2px 3px;
behavior: url(/PIE.htc);

  back...

Speed up response time in development after a Sass change

When working with large Sass files you will notice that the first request after a change to a Sass file takes quite some time. This is because the CSS files are being generated from the Sass files the moment the application answers your request (Sass looks at the files and recompiles if the timestamp changed); it takes even longer when you build sprites with the Lemonade gem.

To avoid this, have Sass watch the files for changes and compile them into CSS files immediately. Th...

Synchronize a Selenium-controlled browser with Capybara

When you click a link or a press a button on a Selenium-controlled browser, the call will return control to your test before the next page is loaded. This can lead to concurrency issues when a Cucumber step involves a Selenium action and a Ruby call which both change the same resources.

Take the following step which signs in a user through the browser UI and then sets a flag on the user that was just signed in:

Given /^the user "([^"]*)" signed in (\d) days ago$/ do |name, days|
  visit new_session_path
  fill_in 'Username', :w...

Simple database lock for MySQL

Note: For PostgreSQL you should use advisory locks. For MySQL we still recommend the solution in this card.


If you need to synchronize multiple rails processes, you need some shared resource that can be used as a mutex. One option is to simply use your existing (MySQL) database.

The attached code provides a database-based model level mutex for MySQL. You use it by simply calling

Lock.acquire('string to synchronize on') do
  # non-th...

How to change MySQL's data directory

  1. Have a backup.

  2. Stop MySQL:

    sudo service mysql stop
    
  3. Move (or copy) your mysql directory. If you want /mnt/mysql to be the new directory, do it like this:

    sudo mv /var/lib/mysql /mnt/
    
  4. Open your MySQL configuration (sudo vim /etc/mysql/my.cnf) and change the datadir value to your new path (e.g. /mnt/mysql)

  5. Modify your AppArmor configuration:

    sudo vim /etc/apparmor.d/usr.sbin.mysqld
    

    Change/copy the lines granting access to /var/lib/mysql to your new path. Otherwise MySQL will not ...

HTML5 and Web Video: Questions for the Industry from the Community

What are Google’s plans for turning WebM into a genuinely open standard, one that is based on consensus like the rest of W3C’s HTML5 effort? Would Google fully support such an effort? Even the WebM project’s domain is controlled by Google. Google chose to release WebM under the Creative Commons license which would theoretically allow a standards body to use the specification as a basis for a truly open standard. Would Google agree to adopt the specification and changes that would emerge from an open process in a timely and robust manner? Wha...

Speed up file downloads with Rails, Apache and X-Sendfile

When you use the send_file method to send a local file to the browser, you can save resources on the application server by setting the :x_sendfile option to true. This option is activated by default for Rails 3, so you need to understand this.

What this option does is not to send any data at all, but rather set the local file path as a new response header:

X-Sendfile: /opt/www/awesome-project/shared/downloads/image.png

When the response comes back from Rails to...