Today I Learned

15 posts by clemenspark

Regexes are supported by Capybara has_content?

Problem

I am trying to assert the presence of a button on the page by checking the button text:

expect(page).to have_content("Close")

Unfortunately, the page also has a dropdown that contains the option Closed.

Solution

Regex to the rescue!

expect(page).to have_content(/Close\b/)

Send commands to all panes in iTerm

Problem

I just edited my shell profile (~/.zshrc). Now I need to remember to reload any pane that needs the changes.

Solution

Send commands to all panes:

  1. Cmd + Shift + I
  2. source ~/.zshrc

Magic!

Am I executing the correct executable?

Q: When I run a command (let's say rails), which executable is it executing?

A:

> which rails
/Users/username/.rvm/gems/ruby-2.1.6/bin/rails

Q: Ah, I see which one it's running. And it's not the right one! Where are all the potential executables, given the current PATH?

A:

> where rails
/Users/username/.rvm/gems/ruby-2.1.6/bin/rails
/usr/bin/rails

Now I know whether it's a PATH ordering issue, or whether it's not included PATH at all.

Configuring a Rails app to redirect http to https

Problem

I have a Rails app on Heroku that is serving up a site on http and https. Google oAuth's callback URL is for https, so attempting to log into the site from the http URL fails.

Solution

The intention was to serve up the site just from the https url, so the solution is to configure Rails to redirect all http traffic to https.

In config/production.rb:

  config.force_ssl = true

Resource: http://stackoverflow.com/questions/27377386/force-ssl-for-heroku-apps-running-in-eu-region

A quick deep dive into 'rake gettext:find'

Problem

I am using Ruby Gettext to manage translations. But today, when I ran rake gettext:find to update my PO files, none of them got updated.

Why??

The Investigation

After some digging, I noticed that Ruby Gettext defines one FileTask (a specific type of Rake task) per PO file, which delegates the work to GNU gettext.

FileTask looks at the timestamps of dependent files, and only executes the supplied block if any of the dependent files have a timestamp later than the file to update.

For example:

dependent_files = ["translations_template_file.pot"]
file "file_to_update" => dependent_files do
  # update the file
end

Why gettext:find was not doing anything

It turned out that gettext uses two FileTasks.

One to update the template:

files_needing_translations = ["file1.js", "file2.rb"]
file "translations_template_file.pot" => files_needing_translations do
  # update the translations template file
end

and another to update the PO file:

file "en-US/translation_file.po" => ["translations_template_file.pot"] do
  # update "en-US/translations.po"
end

The reason gettext:find did not do anything was because none of the files needing translation were updated, thus no PO files were updated.

Solution

> touch one_of_the_files_that_gettext_looks_at.js
> rake gettext:find

Rolling back Rails migrations

There are a bunch of ways to roll back migrations, so I figured I'd capture them in Q & A format.

Let's say the following migration files exist:

> ls db/migrate

20160613172644_migration_1
20160614173819_migration_2
20160615142814_migration_3
20160615160123_migration_4
20160615174549_migration_5

Q: How do I roll back the last migration.
A: rake db:rollback

Q: How do I roll back the last 3 migrations?
A: rake db:rollback STEP=3

Q: How do I roll back a specific migration?
A: rake db:migrate:down VERSION=20160615142814
Details:
The timestamp comes from the filename: 20160615142814_migration_3

and... the one I learned today:

Q: How do I roll back all the migration past a certain version?
A: rake db:migrate VERSION=20160615142814.
Details:
The above will keep the following:

20160613172644_migration_1
20160614173819_migration_2
20160615142814_migration_3

and roll back the following:

20160615160123_migration_4
20160615174549_migration_5

In other words, it will keep all the migrations upto and including the version you specified.

Prettify JSON in the browser console

Problem

I want to check the shape of data for an XHR request in Chrome. So I go to the Network panel in the inspector.

When I check the response tab, I see the following:

[{"id":43,"child_node":{"active":true,"name":"name","created_at":"2015-05-25T16:55:09.600-04:00"},"notes":null}]

Not very inspectable.

When I check the preview tab, it's a fancy preview mode, with all the nodes folded:

v [{id: 43,…}, {id: 44,…}, {id: 46,…}, {id: 45,…}]
> 0: {id: 43,…}
> 1: {id: 44,…}
> 2: {id: 46,…}
> 3: {id: 45,…}

Not easy to check the shape of the data either.

Solution

JSON.stringify to the rescue!

function prettifyJson(json) {
  console.log(JSON.stringify(
    json,      // copied from Response tab
    undefined, // ignore this argument (or read link below)
    2          // spaces to indent
  ));
};

Paste the above into the Chrome inspector.

Then copy the response in the response tab, and call the function:

>> prettifyJson([{"id":43,"child_node":{"active":true,"name":"name","created_at":"2015-05-25T16:55:09.600-04:00"},"notes":null}])

Output:

[
  {
    "id": 43,
    "child_node": {
      "active": true,
      "name": "name",
      "created_at": "2015-05-25T16:55:09.600-04:00"
    },
    "notes": null
  }
]

// Tada!!

Resource:

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

Using WIP acceptance specs

Context

I usually follow the following approaching when working on a story:

  1. Write a failing acceptance spec.
  2. Do a spike to validate the proposed solution. Get the spike to pass.
  3. Capture learnings, and blow away the spike changes.
  4. Properly TDD away at the solution.

One annoyance with this approach was:

What do I do with the failing acceptance spec?

I usually try not to commit failing specs, since that makes git bisect less useful when I'm trying to see what broke it.

Solution

RSpec tags to the rescue.

Configure your specs to ignore wip specs by default:

RSpec.configure do |c|
  c.filter_run_excluding wip: true
end

Write a WIP spec:

it 'tests my yet-to-be-added feature', :wip do
  "my test"
end

Run the spec:

rspec my_acceptance_spec.rb --tag=wip

The acceptance spec can be committed, because it won't run as part of your regular test suite.

Once the story is done, make sure you remove the :wip flag!

Enhancing rake tasks

Problem

I have a rake task, and I want to make it do something before and after it's done.

task :a_task do
  puts "task"
end

task :setup_task do
  puts "setup"
end

task :run_after do
  puts "after"
end

What are my options?

Solution

For pre-req tasks, this is what is often done:

task :a_task => [:setup_task] do
  puts "task"
end

task :setup_task do
  puts "setup"
end
> rake a_task
setup
task

However, this requires modifying the existing task. This might not even be an option for rake tasks from 3rd party gems. We can do better: Enhance the task!

task :a_task do
  puts "task"
end

task :setup_task do
  puts "setup"
end

Rake::Task[:a_task].enhance [:setup_task]
> rake a_task
setup
task

To run a task (or any code for that matter) after a rake task:

task :a_task do
  puts "task"
end

task :run_after do
  puts "after"
end

Rake::Task["a_task"].enhance do
  Rake::Task["run_after"].invoke
end
> rake a_task
task
after

Source: http://www.dan-manges.com/blog/modifying-rake-tasks

Disabling emdash substitutions in OSX apps

Problem

I use the slack app on my Mac, but it keeps replacing double dashes with an emdash.

e.g. --stat becomes —stat

Solution

In the slack app (and many other apps I presume?), right-click the field that has the problem, and turn off this option:

Substitutions -> Smart Dashes

Diffing a topic branch against the base branch

I often want to check all the changes made in my branch, relative to the base branch. Let's say the base branch is master.

Most of the time, I use plain ol' git diff.

git diff master
git diff master --name-only  # only list the changed files

However, git diff master doesn't always work. For example, if I pulled the latest changes in master, and haven't rebased my branch, then git diff master will show all kinds of changes I didn't make.

So what is a dev to do?

git merge-base to the rescue!

Here's the description from git help merge-base:

Find as good common ancestors as possible for a merge

The following gives me a good commit to compare against:

> git merge-base master HEAD
0783e77e5ca810e36fc7080753ac62526c09d0e4

Therefore, I can check all my changes using:

git diff `git merge-base master HEAD`

zsh function:

gdb() {
  git diff `git merge-base master HEAD` $@
}

Mass replace and copy by file extension

Problem

I just cloned a Rails project. There are a bunch of files with the .yml.sample extension under the config directory.

I'd like to copy all those files without the .sample prefix.

Solution

zsh functions to the rescue!

Add this to your .zshrc file:

autoload -U zmv

Then run:

zmv -C 'config/(*.yml).sample' 'config/$1'

By default, zmv will move files. -C puts it in copy mode.

For more info:

man zshcontrib

Capybara !has_content? vs has_no_content?

Let's say you're using RSpec and Capybara.

What's the difference between the following:

  expect(page).to_not have_content("not on page")

and

  expect(page).to have_no_content("not on page")

Assuming that the content not on page is expected to disappear from the page:

The first one will wait until the Capybara default wait time is over (2 seconds), then pass the assertion. The second one will pass as soon as not on page disappears from the page.

The reason the first one waits is because has_content? waits for the content to appear. When the timeout expires, it returns false, which passes the to_not assertion.

Never use to_not have_content or !has_content in Capybara.

Using git stash for spiking

Often, I do a small spike to see if a certain code change makes sense. When it's time to actually make code changes, I want to start from scratch to do proper TDD. However, sometimes I want to reference the code I spiked out to guide me.

One option is to stash away the spike, and reference it using:

git stash show -v

This will show you the contents of the most recently stashed code.

If it's not the most recently stashed change, you can specify the stashed change you want to see:

git stash list
git stash show -v @{2}

Jumping/deleting by matching tags

Let's say you have the following:

def a_method
  "a return value"
end

If you put your cursor on def and type %, it goes to end.

If you put your cursor on def and type d%, it deletes the entire method!