Detect the current Rails environment from JavaScript or CSS

Detecting if a Javascript is running under Selenium WebDriver is super-painful. It's much easier to detect the current Rails environment instead.

You might be better of checking against the name of the current Rails environment. To do this, store the environment name in a data-environment of your <html>. E.g., in your application layout:

<html data-environment=<%= Rails.env %>>

Now you can say in a pi...

How to: Store multiple Vim commands in macros and recall them

Vim allows recording a batch of commands as a macro. This is handy if you need to do the same things over and over.

Here is how:

  1. Press q to enter macro mode.
  2. Press a letter (not a number!) key to assign a slot to your macro.
  3. You are now recording. Do whatever you want with usual commands.
  4. Once you are done, press q again to stop recording.
  5. You can now run your recorded macro by pressing @ and its assigned letter key.

Cheats:

  • If you want to run a macro repeatedly, type a number before pressing the @ key. Example: ...

How to stub class constants in RSpec

Hint: There's another card with this helper for Cucumber features.


Sometimes you feel like you need to stub some CONSTANT you have defined in an other class. Since actually constants are called constants because they're constant, there's no way to easily stub a constant.

Here are three solutions for you.

Easiest solution

Rethink! Do you really need CONSTANT = %w[foo bar] to be constant? In many cases, setting it as a...

Always store your Paperclip attachments in a separate folder per environment

tl;dr: Always have your attachment path start with :rails_root/storage/#{Rails.env}#{ENV['RAILS_TEST_NUMBER']}/.


The directory where you save your Paperclip attachments should not look like this:

storage/photos/1/...
storage/photos/2/...
storage/photos/3/...
storage/attachments/1/...
storage/attachments/2/...

The problem with this is that multiple environments (at least development and test) will share the same directory structure. This will cause you pain eventually. Files will get overwritten and...

Nginx Error "413 Request Entity Too Large"

If you get the error "413 Request Entity Too Large" from Nginx client_max_body_size is too low (default is client_max_body_size=1m).

This can happen for example during file upload.

Check whether a Paperclip attachment exists

Don't simply test for the presence of the magic Paperclip attribute, it will return a paperclip Attachment object and thus always be true:

- if user.photo.present? # always true
  = image_tag(user.photo.url)

Use #exists? instead:

- if user.photo.exists?
  = image_tag(user.photo.url)

How to grep through the DOM using the Capybara API

When your Cucumber feature needs to browse the page HTML, and you are not sure how to express your query as a clever CSS or XPath expression, there is another way: You can use all and find to grep through the DOM and then perform your search in plain Ruby.

Here is an example for this technique:

Then /^I should see an image with the file...

Rails I18n fallback locales

When you need to create a locale for a language variant (like Austrian for German), you probably don't want to duplicate your entire de.yml file only to change a few minor exceptions for our Austrian friends.

Luckily, the I18n gem used by Rails has a fallback feature where you can make one locale file fall back to another if no translation is available.

In the example above you would have a config/locales/de_DE.yml:

de_DE:
  # hundreds of translations here

... and another...

Web Operations 101 For Developers

This post is not about devops, it's not about lean startups, it's not about web scale, it's not about the cloud, and it's not about continuous deployment. This post is about you, the developer who's main purpose in life has always been to build great web applications. In a pretty traditional world you write code, you write tests for it, you deploy, and you go home. Until now.

Responding to the OPTIONS HTTP method request in Rails: Getting around the Same Origin Policy

Code example for implementing Cross-Origin Resource Sharing (CORS) in Rails.

Zip files with Ruby

When you need to zip up files in Ruby, use zipruby.

sudo gem install zipruby

You can add existing files, add files from strings and even add directories.
Example usage:

require 'zipruby'
cars = %w[audi bmw mercedes]

zipfile = Tempfile.new('my.zip', 'tmp')
Zip::Archive.open(zipfile.path, Zip::CREATE) do |zip|
  zip.add_file '/tmp/me.txt'
  zip.add_dir 'cars' 

  cars.each do |car|
    zip.add_buffer "cars/#{car}.txt", "This #{car} is mine!" 
  end
end

Credits go to winebarrel for the Ruby bin...

Hide your Selenium browser window with a VNC server

This is now part of geordi. Please don't follow the instructions below, if you use geordi.

Inspired by the recent headless Selenium note, I found yet another solution for the problem to hide your selenium tests away.

This has the advantages
^

  • not to require a gem (so you do not force this on others)
  • to allow you to take a look at the running webdriver if necessary

Simply make a script th...

How to look at hidden X screens

When you have a program running in a hidden X screen (like with Xvfb for Selenium tests) you may want to look at that hidden screen occasionally.

First, find out what X displays are currently active:

netstat -nlp | grep X11

This should give you some results like these:

unix  2      [ ACC ]     STREAM     LISTENING     8029600  4086/Xvfb           /tmp/.X11-unix/X99
unix  2      [ ACC ]     STREAM     LISTENING     8616     -     ...

Resque: Work off queues manually

If you're writing a spec for an application using Resque, you may need to work off queues manually without having an external worker running.

For this, you could use ResqueSpec which basically stubs away Resque completely.

If you don't want that, but more closely mimic what actually happens, use this instead:

module Resque

  def self.work_off(*queues)
    if queues.any? { |queue| peek(queue) }
      worker = Work...

How to hide your selenium browser window with "headless"

Note: While the solution in this card should still work, we prefer another solution now: Hide your Selenium browser window with a VNC server.


If you would like to hide the annoying selenium browser window that always gets the focus and prevents you from working, you can use the headless gem. This note provides some instructions how you can get it to work with your cucumber accepta...

RSpec 2.6 supports "any_instance" now

This finally works:
User.any_instance.should_receive(...)
as does
User.any_instance.stub(...)

Note: You won't have RSpec 2.6 if you're still working on Rails 2.

How to use different encodings for text in HTTP headers

In order to use different encodings than ASCII for HTTP headers use the following syntax:

Header-Key: Header-Value; Parameter-Name*=utf-8''parameter_value_in_utf8_and_encoded_chars

Concrete example how to use an utf8 encoded filename for file downloads (with fallback):

Content-Disposition: attachment; filename="aepfel"; filename*=utf-8''%c3%a4pfel

Linux: Create file of a given size

Sometimes you need a file of some size (possibly for testing purposes). On Linux, you can use dd to create one.

Let's say you want a 23 MB file called test.file. You would then run this:

dd if=/dev/zero of=test.file bs=1048576 count=23

The block size (bs) is set to 1 MB (1024^2 bytes) here, writing 23 such chunks makes the file 23 MB big.\
Adjust to your needs.

This linux command might also come in handy in a Ruby program. It could be used like:

mb = 23
mb_string, _error_str, _status = Open3.capture3('dd if=/dev/zero...

Running the Awesome window manager within Gnome

Note: Consider using MATE instead of Gnome 3 on newer system

Awesome is a very good tiling window manager that provides neat features like automatic layouting of windows, good multi-display support with per display workspaces and more. Unfortunately, it is only a window manager, and lacks a lot of Gnome's conveniences like the network manager, application menus, automatic updates etc.

Fortunately, Gnome allows you to selectively replace only the win...

Check gem dependencies before installation

With gem dependency it is possible to check the dependencies for your gem before you install it.

Here is an example output for Nokogiri:

Gem nokogiri-1.4.4
  hoe (>= 2.6.2, development)
  minitest (>= 1.6.0, development)
  racc (>= 0, development)
  rake-compiler (>= 0, development)
  rexical (>= 0, development)
  rubyforge (>= 2.0.4, development)

Configuring ActionMailer host and protocol for URL generation

When you generate a URL in a mailer view, ActionMailer will raise an error unless you previously configured it which hostname to use.

There are two options to set the default_url_options of ActionMailer:

  1. Hardcoded solution (preferred solution when using Rails with ActiveJob/Sidekiq or Cronjobs)
  2. Dynamic solution

1. Hardcoded solution

When you are sending mails from outside the request cycle, e.g. ActiveJob/Sidekiq or Cronjobs, y...

Fix slow specs using SOLR

I've recently encountered a weird problem with specs making lots of SOLR queries using the acts_as_solr plugin: After a certain number of specs, exactly one spec suddenly took over 30 seconds to finish.

It turns out that for some reason, the SOLR server seemed not to close its HTTP connections properly. After the maximum number of connections was reached, the next spec needed to wait for an old connection to time out.

I'm not exactly sure why this happened, why it only seems to be happening in specs and which part of the code is actually...

Traverse large XML files with Nokogiri

If you need to parse a large XML file (> 20 MB or so), you should parse it in chunks, otherwise it will need lots of memory.

Nokogiri offers a reader that lets you parse your XML one node at a time.

Given an XML library.xml with this content

    <library>
      <book>
        <title>...</title>
        <author>...</author>
      </book>
      <book>
         ...
      </book>
       ...
    </library>

you can for example loop over all books with

    def each_book(filename, &block)
      File.open(filename) do |file|
      ...

Capybara steps to match stuff within any selector

These steps are now part of Spreewald.

Since Capybara 0.4.1 a within scope will only look at the first element that matches. We find this behavior to be impractical, but it is by design.

In order to perform a test or action in all matching elements, do not use within but prefer the attached "inside any" Cucumber steps like these:

When I follow "Foo" inside any "table"
Then I should see "Bar" inside any "li"