RabbitMQ Publisher Confirms with Bunny

Tagged bunny, confirms, publisher, rabbitmq  Languages ruby

Source https://github.com/ruby-amqp/bunny/blob/master/examples/guides/extensions/publisher_confirms.rb:

require "bunny"

puts "=> Demonstrating publisher confirms"

conn = Bunny.new

ch   = conn.create_channel
x    = ch.fanout("amq.fanout")
q    = ch.queue("", :exclusive => true).bind(x)

1000.times do
ch.wait_for_confirms # blocks calling thread until all acks are received

sleep 0.2
puts "Received acks for all published messages. #{q.name} now has #{q.message_count} messages."

sleep 0.7
puts "Disconnecting..."

How to call JavaScript code from Ruby

Tagged therubyracer, execjs, javascript, ruby  Languages js, ruby, javascript


source 'https://rubygems.org'
gem "therubyracer"
# commonjs.rb provides 'require' needed to import modules
gem 'commonjs'


require 'v8'
require 'commonjs'
env = CommonJS::Environment.new(V8::Context.new, path: './node_modules')
env.require('add.js').add(2, 2)


function add(a, b) {
  // Require works, if the package is available in node_modules
  // require('xyz');
  // Console is not available by default
  // console.log(msg);
  return a + b;

exports.add = add;
$ bundle exec ruby add_with_javascript.rb

Tested with:

  • commonjs (0.2.7)
  • libv8 (
  • therubyracer (0.12.3)

Set the accept-language header in Capybara / Selenium WebDriver tests

Tagged capybara, selenium, ruby  Languages ruby

To change the accept-language header that Chrome sends with each request in Capybara tests, add the ‘selenium-webdriver (3.142.6)’ preference to the driver’s options:

  opts.add_preference('intl.accept_languages', 'sv')


Capybara.register_driver :chrome do |app|
  caps = Selenium::WebDriver::Remote::Capabilities.chrome(loggingPrefs: { browser: 'ALL' })
  opts = Selenium::WebDriver::Chrome::Options.new
  opts.add_preference('intl.accept_languages', 'sv')
  chrome_args = %w[--no-sandbox --disable-popup-blocking --enable-features=NetworkService,NetworkServiceInProcess --window-size=1920,1080]
  chrome_args.each { |arg| opts.add_argument(arg) }
  Capybara::Selenium::Driver.new(app, browser: :chrome, options: opts, desired_capabilities: caps)

Tested with:

  • capybara (3.30.3)
  • selenium-webdriver (3.142.6)

Which version of Ruby to use with Rails?

Tagged version, rails, ruby  Languages 

To know which version of Ruby is safe to use with Rails one option is to look at the Travis configuration, for example, Rails 5.2: https://github.com/rails/rails/blob/ee1278cc841a883835918fbedb70add96c84543b/.travis.yml#L64-L69

Note the allowed_failures configuration: https://github.com/rails/rails/blob/172bb64ca8d3f1cf88ca7daa4f6a58436e577c69/.travis.yml#L145-L148

This works for Rubygems too: https://github.com/bblimke/webmock/blob/a3c8de2550122d0998cb47292be0bbd2e3f203bf/.travis.yml#L4-L14

Optimistic locking in Rails

Tagged edit conflict, rails, optimistic locking, optimistic lock  Languages ruby, slim

This code is an adaptation of the code found in this Railscasts article: http://railscasts.com/episodes/59-optimistic-locking-revised?view=asciicast


module OptimisticLocking
  extend ActiveSupport::Concern

  included do
    validate :handle_conflict, on: :update

  def original_updated_at
    @original_updated_at || updated_at.to_f
  attr_writer :original_updated_at

  def handle_conflict
    return unless @conflict || updated_at.to_f > original_updated_at.to_f

    @conflict = true
    # By setting original_updated_at to nil the edit conflict is ignored on a second form submit
    @original_updated_at = nil

    errors.add :base, I18n.t('activerecord.edit_conflict.message')
    changes.each do |attribute, values|
        I18n.t('activerecord.edit_conflict.was', value: values.first)


class Project < ApplicationRecord
  include OptimisticLocking


- object.errors[:base]&.each do |error|
    = icon('fas', 'exclamation-circle')
    =< error


= form @project do |f|
  = render '/edit_conflict', object: @project
  = f.hidden_field :original_updated_at
  = f.text_field :name, class: 'form-control'
  = form_buttons(f, @project)

How to use Rails' form_for with a PostgreSQL array

Tagged string, postgresql, form_for, array  Languages ruby

Using Rails’ form_for with a PostgreSQL array, for example, user roles can be done as follows:


class CreateProjectMembers < ActiveRecord::Migration[6.0]
  def change
    create_table :project_members, id: :uuid do |t|
      t.string :roles, array: true, default: []


class ProjectMember < ApplicationRecord
  validate :validate_roles
  ROLES = %w[administrator collaborator].freeze

  def validate_roles
    return if roles.is_a?(Array) && roles.all? { |d| ROLES.include?(d) }

    errors.add(:roles, :invalid)

View (slim-lang):

= form @project_member do |f|
    = f.label :roles, 'Roles'
    = f.check_box :roles, { label: 'Administrator', multiple: true }, 'administrator', nil
    = f.check_box :roles, { label: 'Collaborator', multiple: true }, 'collaborator', nil


class ProjectMembersController < ApplicationController
  def update
    if @project_member.update(project_member_params)

  def project_member_params
    params.require(:project_member).permit(roles: [])

Note that if you have a “has_many through” relationship, instead of a PostgreSQL array, you can simply use:

= f.collection_check_boxes(:locale_ids, Locale.all, :id, :language) do |b|

Reference: https://apidock.com/rails/v6.0.0/ActionView/Helpers/FormOptionsHelper/collection_check_boxes

How to dump Postgres extensions and all schemas with Rails

Tagged migration, rails, wtf, lol  Languages bash, ruby

When running rake db:reset you might get one of the following informative errors:

  function public.gen_random_uuid() does not exist
  db/structure.sql:22: ERROR:  schema "public" already exists

To fix them tell Ruby to dump everything by editing config/application.rb:

module XXX
  class Application < Rails::Application
    config.active_record.dump_schemas = :all

Tested with Rails 6.

References: https://github.com/rails/rails/issues/17157#issuecomment-77400517

How to fix "if the extend should be able to fail" and "undefined variable" SCSS errors

Tagged sprockets, extend, rails, scss  Languages bash

If you get an error similar to one of these:

Use “@extend .navbar-inverse !optional” if the extend should be able to fail”:

Undefined variable: $some_variable

The solution might be the one explained here.

My issue was that I had the SCSS partials in the root folder like this:

❯ tree app/assets/stylesheets
├── application.scss
├── _bootstrap-custom.scss
├── _bootstrap-overrides.scss
└── _theme.scss

The problem with this flat folder structure is that all the SCSS files, including partials, are compiled separately. This is the case with Rails’ Sprockets at least.

The solution for me was to move all partials into a subdirectory, like this:

❯ tree app/assets/stylesheets
├── application.scss
├── partials
│   ├── _bootstrap-custom.scss
│   ├── _bootstrap-overrides.scss
│   ├── _theme.scss
└── vendor
    └── introjs.min.css

This way Sprockets, which compiles SCSS in Rails applications, will only compile the application.scss, which includes the partials.



You will have to edit the manifest.js to specify those files.

You may also find that some files that were not previously compiled as top-level targets now are. For instance, if your existing app has any js files directly at ./app/assets/javascripts or css/scss files ./app/assets/stylesheets, Rails with Sprockets 4 will now compile them as top-level targets. Since they were not previously treated as such, you probably don’t mean them to be; if they are .scss partials referencing variables meant to be defined in other files, it may even result in an error message that looks like Undefined variable: $some_variable.

To correct this, you can move these files to some subdirectory of ./app/assets/stylesheets or javascripts; or you can change the manifest.js to be more like how Rails with Sprockets 3 works, linking only the specific application files as top-level targets:

Rails log:

2019-12-19 15:52:49 +0200: Rack app error handling request { GET / }
#<ActionView::Template::Error: Error: "#nav" failed to @extend ".navbar-inverse".
       The selector ".navbar-inverse" was not found.
       Use "@extend .navbar-inverse !optional" if the extend should be able to fail.
        on line 64:11 of app/assets/stylesheets/_theme.scss
>>   @extend .navbar-inverse;

/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sassc-2.2.1/lib/sassc/engine.rb:49:in `render'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/sassc_processor.rb:59:in `block in call'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/utils.rb:138:in `module_include'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/sassc_processor.rb:58:in `call'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/sassc_processor.rb:31:in `call'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:84:in `call_processor'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:66:in `block in call_processors'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:65:in `reverse_each'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:65:in `call_processors'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:22:in `block in <class:CompositeProcessor>'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:33:in `call'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:84:in `call_processor'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:66:in `block in call_processors'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:65:in `reverse_each'
/Users/christian/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:65:in `call_processors'

How to encrypt/decrypt a file with GPG

Tagged decrypt, password, gpg, encrypt  Languages bash

First, install GPG:

brew install gpg

To encrypt a file with GPG, run:

gpg -c secrets.txt

To decrypt the encrypted and password-protected GPG file, run:

gpg secrets.txt.gpg

failed to push some refs to

Tagged rebase, push, git, pull  Languages bash

git push fails:

❯ git push
To github.com:xxx/yyy.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:xxx/yyy.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Use pull and rebase to rewind and replay your commit, otherwise you will end up with a “merge commit” in your git history:

❯ git pull --rebase
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 2), reused 3 (delta 2), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:xxx/yyy
   aaa..bbb  master     -> origin/master
First, rewinding head to replay your work on top of it...
Applying: <Your commit message>.

How to Undo Almost Anything With Git: https://github.blog/2015-06-08-how-to-undo-almost-anything-with-git/

Git Pretty - Git Flowchart: http://justinhileman.info/article/git-pretty/

Oh Shit, Git!?!: https://ohshitgit.com/