Test redirects to an external URL with Cucumber/Capybara

When a controller action redirects to an external URL (like http://somehost.com/some/path) you will find that this is hard to test with Cucumber and Capybara:

  • A non-Javascript Rack::Test scenario will just ignore the host and try to open /some/path in your local application
  • A Selenium test will actually follow the redirect, which you probably don't want either

There are two workarounds for this. You can use either, or a combination of both.

  1. Write a controller spec

Controller specs can test if a resp...

How to disable cookies in cucumber tests

Unfortunately, Capybara does not offer a switch to disable cookies in your test browser. However, you can work around that by using a tiny Rack middleware -- it works for both Selenium and non-Selenium tests.


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

Given cookies are disabled
When I try to sign in
Then I should see "Can't sign you in. Please enable cookies."

You can! Put the code below into some place like lib/rack/cookie_stripper.rb.

module Rack
  class CookieStripper
    
    ENABLED = false

...

Cucumber step to set cookies in your Capybara session

To set a cookie in your test browser for cucumber tests, you need to know which driver you are using. Use the step below according to your driver.

Rack::Test

Given /^I have a "([^\"]+)" cookie set to "([^\"]+)"$/ do |key, value|
  headers = {}
  Rack::Utils.set_cookie_header!(headers, key, value)
  cookie_string = headers['Set-Cookie']

  Capybara.current_session.driver.browser.set_cookie(cookie_string)
end

Note that Rack::Utils is only used to find out the correct cookie header string (you don't want to generate it yours...

The Plight of Pinocchio: JavaScript's quest to become a real language - opensoul.org

Great presentation about writing Javascript like you write everything else: Well-structured and tested.

JavaScript is no longer a toy language. Many of our applications can’t function without it. If we are going to use JavaScript to do real things, we need to treat it like a real language, adopting the same practices we use with real languages.

This framework agnostic talk takes a serious look at how we develop JavaScript applications. Despite its prototypical nature, good object-oriented programming principles are still relevant. The...

Ruby: Debugging a method's source location and code

Access the Method object

Dead simple: Get the method object and ask for its owner:

"foo".method(:upcase)
# =>  #<Method: String#upcase> 

"foo".method(:upcase).owner
# => String

Look up a method's source location

Ruby 1.9 adds a method Method#source_location that returns file and line number where that method is defined.

class Example; def method() end; end
# => nil

Example.new.method(:method).source_location
# => ["(irb)", 11] 
 
"foo".method(:upcase).source_location
# => nil # String#upcase is a native method...

Fix „rvm no such file to load -- openssl“ or "rvm no such file to load -- zlib"

For example if you use rvm and get this message:

ERROR:  Loading command: install (LoadError)
    no such file to load -- zlib
ERROR:  While executing gem ... (NameError)
    uninitialized constant Gem::Commands::InstallCommand

You've installed your ruby without having all required libraries.

I don't know why there isn't a Warning message if you install a ruby with rvm and didn't have libraries like openssl and zlib.

To fix this you can execute this:

#to show the requirements for your system
rvm requireme...

Ruby 1.9 or Ruby 2.0 do not allow using shortcut blocks for private methods

Consider this class:

class Foo

  private
  
  def test
    puts "Hello"
  end
  
end

While you can say create a block to call that method (using ampersand and colon) on Ruby 1.8, ...

1.8.7 > Foo.new.tap(&:test)
Hello
=> #<Foo:0x1e253c8> 

... you cannot do that on Ruby 1.9 or 2.0:

1.9.3 > Foo.new.tap(&:test)
NoMethodError: private method `test' called for #<Foo:0x00000001e8c258>

^
2.0.0 > Foo.new.tap(&:test)
NoMethodError: private method `test' called for #<Foo:0x000000027bc738...

MySQL: How to create columns like "bigint" or "longtext" in Rails migrations, and what :limit means for column migrations

Rails understands a :limit options when you create columns in a migration. Its meaning depends on the column type, and sometimes the supplied value.

The documentation states that :limit sets the column length to the number of characters for string and text columns, and to the number of bytes for binary and integer columns.

Using it

This is nice since you may want a bigint column to store really long numbers in it. You can just create it by ...

How to copy your „Google Chrome“ or „Chromium“ profile without creating an online account

Google Chrome saves your profile data in ~/.config/google-chrome.
To transfer the profile to for example a system you have setup freshly do following steps:

  • make a copy of ~/.config/google-chrome
  • install google-chrome
  • restore your backuped profile to ~/.config/google-chrome
  • launch google-chrome

(Replace google-chrome by chromium-browser if you use chromium-browser)

ActiveRecord: count vs size vs length on associations

TL;DR: You should generally use #size to count associated records.

size

  • Counts already loaded elements
  • If the association is not loaded, falls back to a COUNT query

count

  • If a counter cache is set up, returns the cached value
  • Issues a COUNT query else

Caveats

  • If you trigger a COUNT query for an association of an an unsaved record, Rails will try to load all children where the foreign key IS NULL. This is not what you want. To prevent this behavior, you can use unsaved_record.association.to_a.size.
  • `c...

Loading dumps via SSH, unpacking and sourcing them, all with a progress bar

Here is a hacky way to load dumps directly from the source server, without fully copying them over and extracting them first.

It may break horribly for you. This is the dark side of the force.

  1. Install pipe viewer, if you don't have it already: sudo apt-get install pv
  2. Know the location of the dump file on the remote server. We'll use /mnt/dumps/my_project.dump.bz2 in the example below.
  3. Find out the size of the (bzipped) file in by...

MySQL will not use indexes if you query the wrong data type

When MySQL refuses to use your index, there's a number of things that you may be doing wrong. One of them might be conditions with improper data types.

An example

For example, let's assume you have a users table with an email field (varchar) which is indexed.

MySQL will use the index when your query is well-formed:

mysql> EXPLAIN SELECT * FROM users WHERE email = 'foo@example.com';
+----+-------------+-------+-------+----------------------+----------------------+---------+-------+------+-------+
| id | select_type |...

CSS: Combining different length units with calc()

calc() lets you mix CSS units. Ever wanted to give an element "the container's width minus 20px on each side"? Here you go:

.foo {
  width: calc(100% - (20px * 2));
}

When using Sass, you need to interpolate Sass expressions:

$margin: 20px * 2

.foo
  width: calc(100% - #{$margin})

Supported by all modern browsers and IE9+.

How to fix: Session hash does not get updated when using "merge!"

tl;dr: Do not use merge! for session hashes. Use update instead.

Outline

Let's assume you're modifying the Rails session. For simplicity, let's also assume your session is empty when you start (same effect when there is data):

# In our example, we're in a Rack middleware
request = Rack::Request.new(env)
request.session.merge! :hello => 'Universe'
request.session
=> {}

Wat?

Even worse: When you inspect your request.session like above (e.g. in a debugger shell, o...

Test xpath expressions in your browser

Safari & Chrome

Use $x() in your console:

$x('//span') # selects all span elements

Firefox

There's an add-on.

JavaScript: Comparing objects or arrays for equality (not reference)

JavaScript has no built-in functions to compare two objects or arrays for equality of their contained values.

If your project uses Lodash or Underscore.js, you can use _.isEqual():

_.isEqual([1, 2], [2, 3]) // => false
_.isEqual([1, 2], [1, 2]) // => true

If your project already uses Unpoly you may also use up.util.isEqual() in the same way:

up.util.isEqual([1, 2], [2, 3]) // => false
up.util.isEqual([1, 2], [1, 2]) // => true

If you are wri...

MongoMapper for Rails 2 on Ruby 1.9

MongoMapper is a MongoDB adapter for Ruby. We've forked it so it works for Rails 2.3.x applications running on Ruby 1.9. [1]

makandra/mongomapper is based on the "official" rails2 branch [2] which contains commits that were added after 0.8.6 was released. Tests are fully passing on our fork for Ruby 1.8.7, REE, and Ruby 1.9.3.

To use it, add this to your Gemfile:

gem 'mongo_mapper', :git => 'git://github.com/makandra/mongomapper.git', :branch => 'rails2'

...

Selenium: How to close another tab (popup)

If you open a pop-up window [1] in your Selenium tests and you want to close it, you can do this:

# Find our target window
handle = page.driver.find_window("My window title")

# Close it
page.driver.browser.switch_to.window(handle)
page.driver.browser.close

# Have the Selenium driver point to another window
last_handle = page.driver.browser.window_handles.last
page.driver.browser.switch_to.window(last_handle)

Mind these:

  • find_window returns a window handle, which is something like `"{485fa8bd-fa99-...

How to silence UTF-8 warnings on Rails 2.3 with Ruby 1.9

Rails 2.3.16+ on Ruby 1.9 causes warnings like this:

.../gems/activesupport-2.3.17/lib/active_support/core_ext/string/output_safety.rb:22: warning: regexp match /.../n against to UTF-8 string

Many thanks to grosser for supplying a monkey-patch for Rails 2.3 (Commit f93e3f0ec3 fixed it for Rails 3). Just put it into config/initializers/ to make those warnings go away.

Since we're using RSpec on mos...

Capturing signatures on a touch device

If you need to capture signatures on an IPad or similar device, you can use Thomas J Bradley's excellent Signature Pad plugin for jQuery.

To implement, just follow the steps on the Github page.

The form

If you have a model Signature with name: string, signature: text, you can use it with regular rails form like this:

- form_for @signature, :html => { :class => 'signature_form' } do |form|
  %dl
    %dt
      = form...

How to fix: Microphone recording levels are too quiet (or get lowered automatically)

If others on a call (Skype, SIP, ...) can not hear you loud enough, your volume levels are probably too low. Also, Skype may be changing your mixer levels.

Set a proper recording volume

  1. Open your mixer software (run pavucontrol).
  2. Switch to input devices.
  3. If you have more than one recording device, find the correct one.
  4. Make a test call to a colleague that can tell you if it's too loud or too quiet.
  5. Drag the volume slider for your input device to an adequate level -- for me, 75% (-7.46dB) work fine. 100% is usually way to...

Fix warning "already initialized constant Mocha" with Rails 3.2

You either have an old version of Mocha and an edge version of Rails 3.2, or you have a new version of Mocha and an old version of Rails. The best solution is to update Mocha to the latest version and switch to Rails edge.

If you are using shoulda-matchers or another gem that locks Mocha to an old version, you are out of luck.
More info with many other workarounds that you do not want to use can be found here. A hack to work around this case is to add the following file to lib/mocha/setup.rb:...

Rails SQL Injection Examples

This page lists many query methods and options in ActiveRecord which do not sanitize raw SQL arguments and are not intended to be called with unsafe user input. Careless use of these methods can open up code to SQL Injection exploits. The examples here do not include SQL injection from known CVEs and are not vulnerabilites themselves, only potential misuses of the methods.

Please use this list as a guide of what not to do.

rsl/stringex · GitHub

Stringex is a gem that offers some extensions to Ruby's String class. Ruby 1.9 compatible, and knows its way around unicode and fancy characters.

Examples for stringex's String#to_url method:

# A simple prelude
"simple English".to_url => "simple-english"
"it's nothing at all".to_url => "its-nothing-at-all"
"rock & roll".to_url => "rock-and-roll"

# Let's show off
"$12 worth of Ruby power".to_url => "12-dollars-worth-of-ruby-power"
"10% off if you act now".to_url => "10-percent-off-if-you-act-now"

# You do...