Use a special version of Chrome for selenium (and another for your everyday work)

Sometimes you need a special version of chrome because it has some features you need for testing, like in this card. You do not need to use that Version apart from tests, because you can tweek selenium to use a special version that you set in your environment:

# features/support/chrome.rb
require "selenium/webdriver"

Capybara.register_driver :chrome320x480 do |app|
  
  if driver_path = ENV["CHROME_SELENIUM_BIN...

Implementing social media "like" buttons: Everything you never wanted to know

So you client has asked you to implement a row of buttons to like the URL on Facebook, Twitter and Google+. Here are some things you should know about this.

0. Security considerations

Each "like" button is implemented by including a Javascript on your site. This means you are running fucking remote code on your page. You are giving Facebook, Twitter and Google+ full permission to e. g. copy user cookies. Check with your client if she is cool with that. Also note that if you're site is suggesting security by operating under HTTPS ...

How to combine greps on log files opened with tail -f

In order to chain greps on log files that are opened via tail -f test.log you have to use the --line-buffered command line option for grep.

Imagine you have the following content in your log file.

# content for log/test.log
test foo
bar
test foo bar baz
bla

Now if you would like to grep for lines that contain foo but not bar, you can use the following command chain:

$ tail -f log/test.log | grep --line-buffered "foo" | grep -v "bar"

Output:
test foo    

Disabling Spring when debugging

Spring is a Rails application preloader. When debugging e.g. the rails gem, you'll be wondering why your raise, puts or debugger debugging statements have no effect. That's because Spring preloads and caches your application once and all consecutive calls to it will not see any changes in your debugged gem.

Howto

Disable spring with export DISABLE_SPRING=1 in your terminal. That will keep Spring at bay in that terminal session.

In Ruby, [you can only write environment variables that subproc...

Jasmine: Reset the location when testing code that uses pushState / replaceState

When testing code that uses pushState / replaceState, your browser will appear to navigate away from http://localhost:3000/specs (or wherever you run your Jasmine tests). This is inconvenient, since reloading the document will no longer re-run the test suite.

To remedy this, copy the attached file to a place like spec/javascripts/helpers and #= require it from your tests. It will store the current location before every test and reset if afterwards (using location.replaceState).

How to revert features for deployment, merge back, and how to stay sane

Removing features and merging those changes back can be painful. Here is how it worked for me.\
tl;dr: Before merging back: reinstate reverted features in a temporary branch, then merge that branch.

Scenario

Consider your team has been working on several features in a branch, made many changes over time and thus several commits for each feature.\
Now your client wants you to deploy while there are still stories that were rejected previously and can't be deployed.
...

An incomplete guide to migrate a Rails application from paperclip to carrierwave

In this example we assume that not only the storage gem changes but also the file structure on disc.

A general approach

Part A: Create a commit which includes a script that allows you to copy the existing file to the new file structure.

Part B: Create a commit which removes all paperclip logic and replace it with the same code you used in the first commit

Part A

Here are some implementation details you might want to reuse:

  • Use the existing models to read the files from
  • Use your own carrierwave models to write t...

GitHub Actions: Retrying a failing step

If you have a flaky command you can use the nick-invision/retry to re-try a failing command, optionally with a timeout:

---
...
jobs:
  test:
    ...
    steps:
    - name: Run tests
      uses: nick-invision/retry@v2
      with:
        timeout_seconds: 30
        max_attempts: 3
        command: bundle exec rake spec

Capybara 2.0 has been released

The gem author Jonas Nicklas highlights in a Google Groups post that the release

  • is not backwards compatible to 1.x versions of Capybara
  • does not support Ruby 1.8.x anymore
  • removes confusion with Rails' built in integration tests (you put capybara rspec integration tests into the spec/feature/... folder) and the :type metadata has been changed from :request to :feature
  • throws exceptions when trying to interact with an element whose identifier is...

Firefox ESR Release Calendar

The linked table shows the support lifecycle for Firefox Extended Support Releases (ESR) which we sometimes need to support for enterprise customers.

The ESR cadence works something like this:

  • Firefox ESR freezes the then-current Firefox version for a year.
  • During this year Mozilla backports security patches to the current ESR, but does not add features.
  • Two subsequent ESR releases overlap for three months. This way enterprises have a quarter to test the new version and migrate their clients.

Consul: Querying a power that might be nil

Consul 0.6.1+ gives your Power class a number of static methods that behave neutrally in case Power.current is nil. This allows you to create authorization-aware models that still work when there is no user at the end of a web browser, e.g. on the console, during tests or during batch processes.


You will often want to access Power.current from another model, to e.g. iterate through the list of accessible users:

class UserReport

  def data
    Power.current.users.c...

Bundler for Rails 2.3.x

Update RubyGems and Passenger

Bundler requires Rubygems >= 1.3.6. Run gem update --system if you have an older version.
It also is not compatible with older versions of passenger, so bring that up to date as well (2.2.15 works).

If you installed RubyGems through apt (which you should never do!), you may see a message giving you a hint to use apt to update.
Some people advise to install the 'rubygems-update-1.3.7' gem on Ubuntu systems if you used apt to install RubyGems.
I did that - and lost all...

How to solve Selenium focus issues

Selenium cannot reliably control a browser when its window is not in focus, or when you accidentally interact with the browser frame. This will result in flickering tests, which are "randomly" red and green. In fact, this behavior is not random at all and completely depends on whether or not the browser window had focus at the time.

This card will give you a better understanding of Selenium focus issues, and what you can do to get your test suite stable again.

Preventing accidental interaction with the Selenium window
--------------------...

RSpec: ". not_to include" behaves like ".to exclude"

RSpec is smart when using the include-matcher in combination with .not_to. One could assume that

.not_to include(3, 4, 5)

evaluates to:

NOT( .to include(3, 4, 5) )

However, it behaves like:

.to (NOT include(3) && NOT include(4) && NOT include(5) )

Warning

Using .not_to in combination with the include-matcher doesn't logically negate the final truth value. It instead negates the individual include-expectations for each argument.

Proof

describe 'RSpec' do
  it "doesn't use logical nega...

Using local fonts with Webpack / Webpacker

When we want to use our own (or bought) fonts in an application with Webpack(er), we have two options. We can

  • put the fonts directly into your Webpack's assets folder or
  • write an npm package with an own sass file that can be imported from the Webpack manifest.

Load fonts from your assets folder

The first option turns out to be straightforward: Import the stylesheets in the index.js of the pack you're using:

// webpack_source_path/application/index.js

import './stylesheets/reset'
import...

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'

...

The new Modularity 2 syntax

We have released Modularity 2. It has many incompatible changes. See below for a script to migrate your applications automatically.

There is no does method anymore

We now use traits with the vanilla include method:

class Article < ActiveRecord::Base
  include DoesTrashable
end

When your trait has parameters, use square brackets:

class Article < ActiveRecord::Base
  include DoesStripFields[:name, :brand]
end

Note how you ...

natritmeyer/site_prism

SitePrism gives you a simple, clean and semantic DSL for describing your site using the Page Object Model pattern, for use with Capybara in automated acceptance testing.

The Page Object Model is a test automation pattern that aims to create an abstraction of your site's user interface that can be used in tests. The most common way to do this is to model each page as a class, and to then use instances of those classes in your tests.

If a class represents a page then each element of the page is represented by a method that, when cal...

Running Rails 2 apps with modern MariaDB SQL server

You might have some trouble running a Rails LTS 2 app with MySQL 5.7.

If you don't want to hack Mysql 5.6 into your modern Ubuntu or use the MySQL sandbox, you might want to try MariaDB 10.x.

MariaDB 10.x should work with both old and new Rails applications.

[Switch to MariaDB](https://makandracards.com/makandra/468343-how-...

Upgrade guide for moving a Rails app from Webpack 3 to Webpack 4

Webpacker is Rails' way of integrating Webpack, and version 4 has been released just a few days ago, allowing us to use Webpack 4.

I successfully upgraded an existing real-world Webpack 3 application. Below are notes on everything that I encountered.
Note that we prefer not using the Rails asset pipeline at all and serving all assets through Webpack for the sake of consistency.

Preparations

  • Remove version locks in Gemfile for webpacker
  • Remove version locks in package.json for webpack and webpack-dev-server
  • Install by ca...

Capybara: How to find a hidden field by its label

To find an input with the type hidden, you need to specify the type hidden:

find_field('Some label', type: :hidden)

Otherwise you will see an exception :

find_field('Some label')
# => Capybara::ElementNotFound: Unable to find field "Some label" that is not disabled`.

Note: Usually you don't need to check the input of hidden fields in an integration test. But e.g. waiting for a datepicker library to write the expected value to this field before continuing the test, which prevents flaky tests, is a valid use case.

Migration from the Asset Pipeline to Webpacker

This is a short overview of things that are required to upgrade a project from the Asset Pipeline to Webpacker. Expect this upgrade to take a few days even the diff is quite small afterwards.

Preparations

1. Find all libraries that are bundled with the asset pipeline. You can check the application.js and the application.css for require and import statements. The source of a library is most often a gem or a vendor directory.
2. Find an working example for each library in the application and write it down.
3. Find out the ver...

Manually requiring your application's models will lead to trouble

In a nutshell:

If you require your Rails models manually, pay attention to the path you use. Unless you have to, don't do it at all.

Background

Consider these classes:

# app/models/user.rb

class User < ActiveRecord::Base
  validate :magic

  def magic
    errors.add_to_base('failed') if bad_things?
  end
end

^
# app/models/foo.rb

require 'user'

class Foo
  # something happens here
end

Now, when your environment is booted, Rails will automatically load your models, like User...

How to organize and execute cucumber features (e.g. in subdirectories)

In cucumber you are able to run features in whatever directory you like. This also includes executing features in subdirectories. There are only some things you have to take care of.

By default, cucumber loads all *.rb files it can find (recursively) within the directory you passed as argument to cucumber.

$ cucumber # defaults to directory "features"
$ cucumber features
$ cucumber my/custom/features/dir

So, if you would like to organize features in subdirectories, you won't have *any problems when running the whole test...