Using the Ruby block shortcut with arguments

Ruby has this handy block shortcut map(&:to_i) for map { |x| x.to_i }. However, it is limited to argument-less method invocations.

To call a method with an argument, you usually need to use the full block form. A common and annoying case is retrieving values from a list of hashes (imagine using a JSON API):

users = [ { name: 'Dominik', color: 'blue' }, { name: 'Stefan', color: 'red'} ]
names = users.collect do |user|
  user[:name]
end

If you're using Rails 5+, this example is covered by Enumerable#pluck (`users.pluck(:name)...

Whenever: Don't forget leading zeros for hours!

Whenever is a Ruby gem that provides a nicer syntax for writing and deploying cron jobs.

Leading zeros are important for whenever if you use the 24-hours format!

This schedule.rb:

every 1.day, at: '3:00', roles: [:primary_cron] do
  runner 'Scheduler.delay.do_things'
end

will lead to this crontab entry (crontab -l) with the default configuration:

0 15 * * * /bin/bash -l -c 'cd /var/www/my-project/releases/20180607182518 && bin/rails runner -e production '\''Scheduler.delay.do_things'\'''

Which would run on 3...

Ruby: All Errno::ERROR constants inherit from SystemCallError

To catch all possible exceptions from a network call, we need to rescue many error classes like this:

rescue SocketError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EHOSTUNREACH, OpenSSL::SSL::SSLError, MyHttpLib::BadResponse

You can shorten this a bit by rescuing SystemCallError, which is a base class for all Errno:: exceptions:

rescue SocketError, SystemCallError, OpenSSL::SSL::SSLError, MyHttpLib::BadResponse

Some high-level ...

ActiveRecord::Store: migrate data in store

When you need to store structured data (like Ruby hashes) in a single database column with ActiveRecord, a simple way is to use PostgreSQL's jsonb columns. ActiveRecord will automatically serialize and deserialize your Hash to and from JSON, and you can index JSON paths for fast reads.

As an alternative, ActiveRecord::Store offers a way to store hashes in a single database column. This card will show you how to migrate those hashes in an ActiveRecord::Migration by example:
...

Capistrano + Rails: Tagging production deploys

Just like Ruby Gems tag their version releases to the corresponding Git commit, it can be helpful to track production deploys within the commit history. This task does the tagging for you.

Capistrano 3

# lib/capistrano/tasks/deploy.rb
namespace :deploy do
  ...

  desc 'Tag the deployed revision'
  task :tag_revision do
    date = Date.today.to_s

    puts `git tag deploy-#{date} #{fetch :current_revision}`
    puts `git push --tags origin`
  end

end
# config/deploy/production.rb
after 'deploy:finished', 'deploy:tag_...

Bundler error: Downloading gem revealed dependencies not in the API

Recent Bundler (1.16.1) started complaining about missing dependencies in the Gemfile. This is due to a stricter handling of specifications (see attached link).

The error message looks like this:

Downloading example-gem-1.2.3 revealed dependencies not in the API or the lockfile (other-gem (< 3)).
Either installing with `--full-index` or running `bundle update example-gem` should fix the problem.

However, bundle install --full-index did not any better for me, and bundle update is not always a viable solution.

Easiest solut...

Fixing: Gem::Package::PathError: installing into parent path is not allowed

This might be a known issue with Rubygems 2.5.1. This will help:

gem update --system

Generating test images on the fly via JavaScript or Ruby

When you need test images, instead of using services like lorempixel or placehold.it you may generate test images yourself.

Here we build a simple SVG image and wrap it into a data: URI. All browsers support SVG, and you can easily adjust it yourself.
Simply set it as an image's src attribute.

JavaScript

Simple solution in modern JavaScript, e.g. for use in the client's browser:

function svgUri(text) {
  let svg = `
    <svg wid...

RubyMine: You can disable inspections you don't care about

When you find yourself constantly ignoring a RubyMine warning, you can simple disable that warning and de-clutter your editor. E.g. in my Cucumber scenarios RubyMine underlines 90% of all lines because it does not know about spreewald, making the file really hard to read.

You can disable any unwanted inspection by opening File / Settings / Editor / Inspections and searching for the warning text.

What you disable or keep is up to your personal preference. I personally disable at least the following...

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-...

Making httpclient use the operating system's SSL cert store

The httpclient gem comes with a custom SSL cert store.

While an customizable, application-level cert store is great when you need to deal with broken or self-signed certificates, you usually want to use the cert store from the underlying Linux. The Linux cert store is updated periodically while httpclient's cert store goes out of date and will eventually not be able to verify certs.

To use the cert store from the underlying operating system:

client = HTTPClient.new
client.ssl_config.cert_store...

Upgrading a Rails app to Cucumber 3

Upgrade gems

You need to update a lof gems. Make sure you don't have any version constraints in your Gemfile or your bundle update won't do anything!

Upgrade cucumber_priority:

bundle update cucumber_priority

Upgrade spreewald:

bundle update spreewald

Upgrade cucumber_factory:

bundle update cucumber_factory

Upgrade parallel_tests:

bundle update parallel_tests

Even on the latest version, parallel_tests will print some deprecation warnings due to using an older formatter A...

PostgreSQL: Upgrading your user to a superuser

Your default postgres user is named like your linux user. That default user has limited access privileges, which can cause issues such as:

  • DatabaseCleaner needs to disable foreign key constraints before it can wipe the database.
  • Importing a remote dump with geordi
  • Asking Postgres to show the storage path of a database

Doing these things without a superuser will show a Postgres error or (in Ruby) raise PG::InsufficientPrivilege.

To do so, the application's PostgreSQL user must be a superuser. ...

How to: Fix incorrect MySQL client library version

Bundler::GemRequireError: There was an error while trying to load the gem 'mysql2'.
Gem Load Error is: Incorrect MySQL client library version! This gem was compiled for 5.5.46 but the client library is 5.6.30.

Same as in Fix "libmysqlclient.so.20: cannot open shared object file: No such file or directory":

gem pristine mysql2

gem pristine re-installs a gem (without re-downloading), re-compiling all native extensions in the process.

Mysql::Error: BLOB/TEXT column can't have a default value

mysql> SELECT @@global.version;
+------------------+
| @@global.version |
+------------------+
| 5.6.30           |
+------------------+
1 row in set (0,00 sec)

MySQL 5.6 Reference Manual says "BLOB and TEXT columns cannot have DEFAULT values".

If you want to run migrations in development here are two variants which might help. If you are not sure about the side effects (e.g. your application is broken when it doesn't set additional default values on application side, too...

How to: Solve gem loaded specs mutex

Use bundler > 1.15 to fix Gem::LOADED_SPECS_MUTEX (NameError).


Given the following project:

ruby -v
ruby 1.8.7

bundler -v
Bundler version 1.13.7

gem -v
1.8.30

rails -v
Rails 3.2.22.1

Running specs or features resulted in:

uninitialized constant Gem::LOADED_SPECS_MUTEX (NameError)

The previous settings described in Maximum version of Rubygems and Bundler for Ruby 1.8.7 and Rails 2.3 (even the rails version was rails 3.2 and not 2.3) seems not to work here, so I used (also described in the ca...

ss: How to show listening ports

Note

netstat has mostly been superseeded by its more modern rewrite ss which nowadays comes pre-installed rather than netstat.
The most common options (especially all that are mentioned in this card) work the same way as they did with netstat

Sometimes it's necessary for you to check which ports are in use on your local machine and which process is using it. To list this information you can use the following command (which is pretty easy to memorize for Germans 🌷):

sudo ss -tulpn
  • t: tcp
  • u: udp
  • l: listening p...

Configuring RubyGems to not install documentation by default

When installing gems, a lot of time is spent building locally installed documentation that you probably never use.

We recommend you disable documentation generation for gem install by default.
Note that Bundler won't install documentation, so this advice applies only when installing gems manually.

If you don't already have it, create a ~/.gemrc file. The gemrc is a Yaml file, so add the following line to add default switches to the gem command.

gem: --no-document

(If you do n...

Katapult 0.3.0 released

Katapult 0.3.0 brings Rails 5 and Ruby 2.5 support with a new design, plus a ton of smaller features, fixes and improvements.

Features

  • Generating a Rails 5.1.4 app on Ruby 2.5.0
  • Dropped asset pipeline in favor of Webpacker
  • The generated application now has a sleek, simple design based on Bootstrap
  • Employing Unpoly
  • New application model DSL shortcut crud for "create a model and a web UI with crud actions"
  • The generated application model is now a transformable e...

Ruby: Using all? with empty collection

Enumerable#all? returns true for an empty collection. This totally makes sense but you have to think about it when making assumptions on relations which might be empty.

[].all?(&:will_never_be_called_here) => true

Example with empty collection

class Researcher < ActiveRecord::Base
  has_many :papers
end

class Paper
  validates :topic, inclusion: { in: ['computer_science', 'mathematics', 'economy'] }
end

Easy goal: Delete all researches who write onl...

Ruby: control flow with throw and catch

This article will show you how to use throw and catch. It's a nice tool to break out of multiple loops when a result is obtained.

Also see our card Ruby: A small summary of what return, break and next means for blocks.

Error during Rails 5 upgrade: Environment data not found in the schema

This error is raised because your old database does not have a configured environment yet, which Rails 5 enforces.

If this error occurs while migrating your parallel test databases, make sure to update the parallel_tests gem first: current versions fix this. If you're still using Cucumber < v3, the latest version of parallel_tests will be 2.18.0.

Writing a README for a project

Rails applications and ruby gems should have a README that gives the reader a quick overview of the project. Its size will vary as projects differ in complexity, but there should always be some introductory prose for a developer to read when starting on it.

Purpose

That's already the main purpose of a project README: Give a new developer a quick overview of the project. In sketching this outline, the README should notify the reader of any peculiarity he needs to know of.

Remember that in a few months, you'll be a kind of "new ...

xlsxtream: Streaming & Fast XLSX Spreadsheet Writer for Ruby

When writing XLSX files, there are gems like rubyXL or axlsx. While they do offer features like formatting or graphs, to represent spreadsheet cells, they have to keep several Ruby objects in memory. When writing huge files, both will become slow and consume lots of memory.

Enter Xlsxtream, a Ruby XLSX library with less features (e.g. no individual cell styles) but which does away with the memory issue by streaming ...