Rails index route for resources named after uncountable substantives

Using uncountable resources is not recommended as it breaks Rails' magic, e.g. when using form_for. You'll always be better off using simple pluralizable resources.


Rails automatically creates path names for routes defined via the resource method. When you put resource 'user' into config/routes.rb, you can call users_path and get the path to the index action in the UsersController: /users.

However, if you have an uncountable resource like Sheep, you cannot access the index action via sheep_path, because it will...

How to circumvent Firefox's "Document expired" page in Selenium tests

When navigating back to a page that was received from a POST request, undesired side effects may happen. Therefore, modern browsers try to keep users from doing so, i.e. Firefox 24 displays an error page explaining what's wrong. If the user presses "Try Again", it shows an additional alert asking whether the user is certain.

Solution

If you need to circumvent this protection, e.g. to test that your application behaves correctly despite being misused, do this:

page.execute_script 'history.back()'
page.execute_script 'retryThis(this)...

Jasmine: Testing AJAX calls that manipulate the DOM

Here is a Javascript function reloadUsers() that fetches a HTML snippet from the server using AJAX and replaces the current .users container in the DOM:

window.reloadUsers = ->
  $.get('/users').then (html) ->
    $('.users').html(html)

Testing this simple function poses a number of challenges:

  • It only works if there is a <div class="users">...</div> container in the current DOM. Obviously the Jasmine spec runner has no such container.
  • The code requests /users and we want to prevent network interaction in our uni...

How to upgrade Cucumber on Rails 3+

  1. Run bundle update cucumber capybara cucumber-rails to update to the newest versions.

  2. Backup your features/support/path.rb to be able to add your own paths again after the cucumber installation script in step 4.

  3. Backup your features/support/env.rb file to be able to reintegrate parts like your blueprints setup:

    ENV["RAILS_ENV"] ||= "cucumber"
    require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
    require 'spec/support/blueprints'
    
  4. Run `$ rails generate cucumber:install --capyba...

Taking screenshots in Capybara

Capybara-screenshot can automatically save screenshots and the HTML for failed Capybara tests in Cucumber, RSpec or Minitest.

Requires Capybara-Webkit, Selenium or poltergeist for making screenshots. They're saved into $APPLICATION_ROOT/tmp/capybara

The attached files contain config for cucumber integration and a Then show me a screenshot step.
If your project uses Spreewald, you can use its Then show me the page step instead.

Inclu...

Action Mailer Previews

Rails includes a way to see what an e-mail will look like.

Integration to RSpec

All you need to do is implement a preview-class in spec/mailers/previews/notifier_preview.rb:

class NotifierPreview < ActionMailer::Preview
  def welcome
    Notifier.welcome(User.first)
  end
end

And adapt the preview load path in your application.rb:

config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews" # For Rails < 7.1
config.action_mailer.preview_paths << "#{Rails.root}/spec/mailers/previews" # For Rails >=...

Managing vendor libraries with the Rails asset pipeline

The benefit of the Rails asset pipeline is that it compiles your stylesheets and javascripts to a single file, respectively. However, the consequences are startling if you don't understand them. Among others, the raw asset pipeline requires you to have all your asset libraries in the same folder, which quickly becomes confusing as your set of assets grows. To overcome this, we have two different solutions.

Custom solution

We are using a custom workaround to keep library files apart in their own directories. To avoid b...

Asset Pipeline Basics

The Rails asset pipeline improves delivery of application assets (javascripts, stylesheets, images, fonts). Here are some basic facts about its inner workings.

No magic

Manifests are the handle on your assets:

app/assets/stylesheets/application.css # use via: stylesheet_link_tag 'application'

The asset pipeline only considers files you explicitly require within your manifest files. The most common directives used in manifests are require some/file and require_tree some/directory. Paths may be **relative to the current director...

Install or update Chromedriver on Linux

Option 0: Download from the official page (preferred)

Chromedriver must be available in your path. You can add ~/bin to your path like this:

echo "export PATH=$PATH:$HOME/bin" >> $HOME/.bash_profile

If you're also using Geordi, disable automatic updating of chromedriver in ~/.config/geordi/global.yml:

a...

The Easiest Way to Parse URLs with JavaScript

A very clever hack to parse a structured URL object is to create a <a> element and set its href to the URL you want to parse.

You can then query the <a> element for its components like schema, hostname, port, pathname, query, hash:

var parser = document.createElement('a');
parser.href = 'http://heise.de/bar';
parser.hostname; // => 'heise.de'
pathname = parser.pathname; // => '/bar'

if (pathname[0] != '/')
  pathname = '/' + pathname // Fix IE11

One advantag...

jpmcgrath/shortener

Shortener is a Rails Engine Gem that makes it easy to create and interpret shortened URLs on your own domain from within your Rails application. Once installed Shortener will generate, store URLS and “unshorten” shortened URLs for your applications visitors, all whilst collecting basic usage metrics.

How to combine "change", "up", and "down" in a Rails migration

Rails migrations allow you to use a change method whose calls are automatically inverted for the down path. However, if you need to some path-specific logic (like SQL UPDATE statements) you can not define up and down methods at the same time.

If you were to define define all 3 of them, Rails would only run change and ignore up and down. However, Rails 4+ features a helper method called reversible:

class MyMigration < ActiveRecord::Migration

  def cha...

Upgrading a Rails 3.2 application to Ruby 2.1 is really easy

Upgrading from Ruby 1.8.7 to 2.1.2 took me an hour for a medium-sized application. It involved hardly any changes except

  • removing the occasional monkey patch where I had backported functionality from modern Rubies
  • Migrating from require to require_relative where I loaded RSpec factories in Cucumber's env.rb (the Rails application root is no longer in the load path by default)
  • replacing the old debugger with byebug
  • removing sytem_timer from Gemfile (see [this SO thread](http://stackoverflow.com/questions/7850216/how-to-inst...

Bootstrap: How to avoid printing link URLs

By default, Twitter Bootstrap's print styles include printing links.

/* Bootstrap's way of printing URLs */
@media print {
  a[href]:after {
    content: " (" attr(href) ")";
  }
}

If you want to turn that off, you can do

/* Don't print link hrefs */
@media print {
  a[href]:after {
    content: none
  }
}

Angular: Caching API responses in Restangular

Restangular can make use of $http's built-in response cache.

# Cache response for single request
Restangular.one('accounts', 123).withHttpConfig({ cache: true }).get();

# Cache responses for all requests (be careful with that, you might work with stale data)
RestangularProvider.setDefaultHttpFields({ cache: true });

To invalidate cached responses e.g. on a state change in UI Router, you can do

@app.run ['$rootScope', '$cacheFactory', ($rootScope, $cacheFactory) ->
  $rootScope.$on '$stateChangeSuccess', ->
    $cacheF...

New Firefox and gem versions for our Selenium testing environment (Ubuntu 14.04+)

Firefox 5.0.1, which we were using for most Rails 2.3 projects, does not run on Ubuntu 14.04 any more. Here is how to update affected projects.

  1. Update (or create) .firefox-version with the content: 24.0
    If you haven't installed Firefox 24 yet, the next time you run tests with Geordi, it will tell you how to install it.

  2. On a Rails 2 project:

How to repair a corrupt PDF

If you have issues with PDFs, fix them like this: pdftk <corrupted_file>.pdf output <fixed_file>.pdf

Background

I had an issue where an included PDF would not show up in a document created with xelatex. This is the relevant line of LaTeX code:

  \AddToShipoutPicture*{ \includegraphics[width=21cm]{/home/dominik/code/ihero/public/system/stationery/original/stationery.pdf} }

The included PDF is a stationery for invoices which users can upload themselves. It did work until someone updated their stationery with a nearly-iden...

bower-rails can rewrite your relative asset paths

The asset pipeline changes the paths of CSS files during precompilation. This opens a world of pain when CSS files reference images (like jQuery UI) or fonts (like webfont kits from Font Squirrel), since all those url(images/icon.png) will now point to a broken path.

In the past we have been using the vendor/asset-libs folder ...

Managing vendor assets in Rails with Bower

bower-rails is a great solution for managing vendored assets in your Rails app. It feels especially much more convenient and easier to update assets when going this way.

bower-rails generates a Bowerfile that works much like the Gemfile you're used to. Just specify your dependencies and run rake bower:install. You can find available packages here.

An example Bowerfile:

# ./Bowerfile
asset 'angular'
asset 'angular-i18n'
asset 'angular-ui-router'
asset 'angu...

Dealing with "TypeError: Converting circular structure to JSON" on JavaScript

JavaScript structures that include circular references can't be serialized with a"plain" JSON.stringify. Example:

a = { name: 'Groucho' };
b = { name: 'Harpo', sibling: a };
a.sibling = b;

Doing a JSON.stringify(a) will throw an error:

TypeError: Converting circular structure to JSON

There is not much you can do about that except specifying a custom serializer function that detects and cleans up circular references. There are existing solutions so you do not need to think of one yourself, like <https://githu...

Use a Bash function to alias the rake command to Spring binstubs or "bundle exec" fallback

There are different ways to run rake:

  • On Rails 4.1+ projects, you have Spring and its binstubs which dramatically improve boot-up time for Rake and similar. You need to run bin/rake to use them.
  • On older projects, you want to run "bundle exec rake" to avoid those ugly "already activated rake x.y.z" errors that hit you when different rake versions are installed for your current Ruby.

Here is a solution that gives you a plain rake command which uses a binstubbed bin/rake if available and falls back to bundle exec rake if necessar...

Using rbenv on Ubuntu 18.04+

We will be installing rbenv and ruby-build from our own fork, not from the Ubuntu sources.

Installing rbenv

  1. Install rbenv:

    git clone https://github.com/rbenv/rbenv.git ~/.rbenv
    

    For Bash:

    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(rbenv init -)"' >> ~/.bashrc
    

    For ZSH:

    echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
    echo 'eval "$(rbenv init -)"' >> ~/.zshrc
    

    Now reinitialize ...

Using the Facebook Graph API

App tokens

For server-to-server requests to the Facebook Graph API you can skip requesting an Oauth token, an instead use the combination of app_id|app_secret as your access token. This token will never expire, and should suffice for retrieving basic information from the Graph API.

http://graph.facebook.com/endpoint?key=value&access_token=app_id|app_secret

Since you don't make requests for a certain user, the Graph API might respond with an error in case you're requesting a resource that requires authenticating as a human...