Geordi 1.5.1 released

  • Improve geordi cucumber: Only attempt @solo run when the specified files contain the @solo tag, skip @solo run if any filename is passed with a line number (e.g. features/example.feature:3)
  • Improve geordi deploy: Find stages by their prefix (e.g. s -> staging, m -> makandra), bundle if needed, check the selected stage exists
  • Improve geordi server: Takes port as argument (e.g. geordi ser 3001), option --public (-P) starts the server with -b 0.0.0.0 to make it accessible from other machines in the local network, e.g. ...

Capistrano: exclude custom bundle groups for production deploy

Capistrano is by default configured to exclude the gems of the groups development and test when deploying to the stages production and staging. Whenever you create custom groups in your Gemfile, make sure to exclude these, if they should not be deployed to the servers. The gems of these groups might not be loaded by rails, however, the deployment process will take longer as the gems will be downloaded and installed to the server.

e.g. to exclude the groups cucumber and deploy, add the following to `config/deploy/production.rb...

Angular isolate scopes: Calling a parent scope function with externally defined arguments

Isolate scopes offer three kinds of variable binding. One of them is &, allowing to bind a property of the isolate scope to a function in the parent scope. Example:

# HTML
<panel proxy="parent.someFunction(arg1, arg2)"></div>

# Coffeescript
@app.directive 'panel', ->
  scope:
    parentFn: '&proxy'
  link: (scope) ->
    scope.parentFn(arg1: 'first', arg2: 'second')

In this dumb example, the panel directive will call its scope's parentFn() function with two arguments, which proxies to parent.someFunction('first', 'second')...

Sass: How to do math with shorthand values inside variables

If you need to modify (e.g. add 2px) a Sass variable that defines multiple values as one (e.g. for short-hand CSS definitions such ass padding), you can by using nth. It's ugly.

While you could split up such variables into multiple values (e.g. combined padding into one for vertical and one for horizontal padding) in your own Sass definitions, when using some framework definitions like bootstrap-sass, those variables are defined outside your reach.

The following is helpful if you really want to use values from such variables. However...

Ruby 2.3 new features

Ruby 2.3.0 has been around since end of 2015. It brings some pretty nice new features! Make sure to read the linked post with its many examples!

Hash#fetch_values

Similar to Hash#fetch, but for multiple values. Raises KeyError when a key is missing.

attrs = User.last.attributes
attrs.fetch_values :name, :email

Hash#to_proc

Turns a Hash into a Proc that returns the corresponding value when called with a key. May be useful with enumerators like #map:

attrs.to_proc.call(:name)
attrs.keys.grep(/name/).map &attrs...

Linux: Find out which processes are swapped out

Processes in Linux might be put into Swap ("virtual memory") occasionally.
Even parts of a single process might be removed from memory and put into Swap.

In order to find out which processes remain within Swap, run this:

sudo grep VmSwap /proc/*/status | egrep -v "0 kB"

Keep in mind Swap is not evil by definition. Some bytes per process beeing put to Swap will not have that much of performance influence.

If you want the Linux virtual memory manager (which is responsible for the decision if and which processes are moved to Swap) to be...

Hack of the day: One-liner to run all Cucumber features matching a given string

The following will search for all .feature files containing a search term and run them using geordi.

find features/ -name '*.feature' | xargs grep -li 'YOUR SEARCH TERM' | sort -u | tr '\n' ' ' | xargs geordi cucumber

If you do not use Geordi, xargs cucumber or similar might work for you.

For details about each command, see [explainshell.com](http://explainshell.com/explain?cmd=find+features%2F+-name+%27*.feature%27+%7C+xargs+grep+-li+%27YOUR+SEARCH+TERM%27+%7C+sort+-u+%7C+tr+%27%5Cn%27+%2...

factory_bot: Re-use partial factory definitions

Let's say you have two factories that share some attributes and traits:

FactoryBot.define do

  factory :user do
    screen_name 'john'
    email 'foo@bar.de'
    trait :with_profile do
      age 18
      description 'lorem ipsum'
    end
  end
  
  factory :client do
    full_name 'John Doe'
    email 'foo@bar.de'
    trait :with_profile do
      age 18
      description 'lorem ipsum'
    end
  end
  
end

You can re-use the shared fields by defining a trait outside the other factory definitions:

FactoryBot.define do

...

How to find disabled fields with Capybara

At least Selenium cannot find disabled fields. Unless you find them explicitly:

find_field 'This is disabled', disabled: true

How to inspect RSS feeds with Spreewald, XPath, and Selenium

Spreewald gives you the <step> within <selector> meta step that will constrain page inspection to a given scope.

Unfortunately, this does not work with RSS feeds, as they're XML documents and not valid when viewed from Capybara's internal browser (e.g. a <link> tag cannot have content in HTML).

Inspecting XML

If you're inspecting XML that is invalid in HTML, you need to inspect the page source instead of the DOM. You may use Spreewald's "... in the HTML" meta step, or add this proxy step fo...

thoughtbot/fake_stripe: A Stripe fake so that you can avoid hitting Stripe servers in tests.

fake_stripe spins up a local server that acts like Stripe’s and also serves a fake version of Stripe.js, Stripe’s JavaScript library that allows you to collect your customers’ payment information without ever having it touch your servers. It spins up when you run your feature specs, so that you can test your purchase flow without hitting Stripe’s servers or making any external HTTP requests.

We've also had tests actually hitting the testing sandbox of Stripe, which worked OK most of the time (can be flakey).

How to fix: "rake db:rollback" does not work

When you run rake db:rollback and nothing happens, you are probably missing the latest migration file (or have not migrated yet).

$ rake db:rollback
$ 

If that happens to you, check your migration status.

$ rake db:migrate:status
   up     20160503143434  Create users
   up     20160506134137  Create pages
   up     20160517112656  Migrate pages to page versions
   up     20160518112023  ********** NO FILE **********

When you tell Rails to roll back, it tries to roll back the latest change that was mi...

How to preview an image before uploading it

When building a form with a file select field, you may want to offer your users a live preview before they upload the file to the server.

HTML5 via jQuery

Luckily, HTML5 has simple support for this. Just create an object URL and set it on an <img> tag's src attribute:

$('img').attr('src', URL.createObjectURL(this.files[0]))

Unpoly Compiler

As an Unpoly compiler, it looks like this:

up.compiler '[image_p...

How to use triple quotes inside a Cucumber docstring

Cucumber's docstrings let you add long strings to a step like this:

# foo.feature
Given this text:
"""
First line
Second line

Second Paragraph
"""

# foo_steps.rb
Given /^this text:$/ |docstring|
  puts docstring.split
end

You see these neat triple double quotes ("""). Now what to do when you need your docstring to contain triple double quotes, too?

# Does not work:
Given this text:
"""
Docstrings work like this:
  """
  Docstring example
  """
You see?
"""

Update: Official solution

You can escape the inner quotes ...

Running the Awesome window manager within MATE

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. Since it is only a window manager, you will probably miss some of MATE's conveniences like the network manager, application menus, automatic updates etc.

Fortunately, you can run Awesome within MATE, by following these steps (tested on Ubuntu MATE 16.04):

Awesome + MATE

  • Create the followi...

How to fix routing error when using concerns in Rails up to 3.2.22.1

tl;dr

  • Don't write resources :people, :concerns => :trashable

  • Write

    resources :people do
      concerns :trashable
    end
    

Why

Writing a controller spec I encountered this error:

Failure/Error: get :index
ActionController::RoutingError:
  No route matches {:controller=>"people"}

caused by this route definition

resources :people, :concerns => :trashable

which renders strange routes:

      trash_person PUT    /people/:id/trash(.:format)             people#check {:concerns=>:trashable}
          ...

Capybara: Find the innermost DOM element that contains a given string

Let's say you want to find the element with the text hello in the following DOM tree:

<html>
  <body>
    <article>
      <strong>hello</strong>
      <strong>world</strong>
    </article>
  </body>
</html>

You might think of XPath's contain() function:

page.find(:xpath, ".//*[contains(text(), 'hello')")

Unfortunately that returns a lot more elements than you expect:

[ <html>...<html>,
  <body>...</body>,
  <article>...</article>,
  <strong>hello</strong> ]

What you need to do instead is to *find all...

Rails route namespacing (in different flavors)

TL;DR There are three dimensions you can control when scoping routes: path helpers, URL segments, and controller/view module.

scope module: 'module', path: 'url_prefix', as: 'path_helper_name' do
  resources :examples, only: :index
end

as → prefixes path helpers: path_helper_name_examples_path and path_helper_name_examples_url
path → prefixes URL segments: /url_prefix/examples
module → nests the controller: controller Module::ExamplesController, found at app/controllers/module/examples_controller.rb with views ...

Geordi 1.3 released

Changes:

  • Geordi is now (partially) tested with Cucumber. Yay!
  • geordi cucumber supports a new @solo tag. Scenarios tagged with @solo will be excluded from parallel runs, and run sequentially in a second run
  • Support for Capistrano 2 AND 3 (will deploy without :migrations on Capistrano 3)
  • Now requires a .firefox-version file to set up a test firefox. By default now uses the system Firefox/a test Chrome/whatever and doesn't print warnings any more.
  • geordi deploy --no-migrations (aliased -M): Deploy with `cap ...

WTF Opera Mini?!

In developing countries like Nigeria, Opera Mini is used by up to 70% of users on mobile.
This is a collection of front-end development features not supported by Opera Mini and, more importantly, some crowdsourced workarounds for them. This isn't about bashing the problem, but figuring out the solution.

Geordi 1.2 released

Changes:

  • Remove some old binaries (commands still exist in geordi) and mark others as deprecated
  • Rewrite deploy command to support most deploy scenarios:
    • master to production
    • feature branch to staging
    • master to staging or production to production (plain deploy)
  • Improve Cucumber command (fixes #18):
    • Fix pass-through of unknown options to Cucumber
    • Add --rerun=N option to rerun failed Cucumber tests up to N times. Reboots the test environment between runs, thus will pick up fixes you made durin...

Git: Keep your repository tidy

When you're using feature branches, they will stack up if you don't delete them after the merge to master. Here's how to tidy them up.

Delete feature branches

Find already-merged branches by running

# On branch master
git branch --merged

You may safely delete each of the listed branches, because they point to commits that are contained in the history of your current branch (i.e. master).

git branch -d my/feature-branch # Delete feature branch locally
git push origin :my/feature-branch # Push *nothi...

How to open a new tab with Selenium

Until recently, you could open a new tab via window.open when using execute_script in Selenium tests. It no longer works in Chrome (will show a "popup blocked" notification).

This is because browsers usually block window.open unless the user interacted with an element for security reasons. I am not sure why it did work via Selenium before.

Here is an approach that will insert a link into the page, and have Selenium click it:

path = "/your/path/here"
id = "helper_#{SecureRandom.hex(8)}"
execute_script <<-JAVASCRIPT
  ...

Make Nokogiri use system libxml2

The nokogiri gem provides different packages for several platforms. Each platform-specific variant ships pre-built binaries of libxml2, e.g. x86_64-linux includes binaries for 64bit Linux on Intel/AMD. This significantly speeds up installation of the gem, as Nokogiri no longer needs to compile libxml2.

However, this also means that for each security issue with libxml2, Nokogiri maintainers have to update their pre-built binaries and release a new version of the gem. Then, you need to update and ...