djberg96/sys-filesystem: A Ruby library for getting filesystem information

Uses FFI and works all relevant operating systems.

If you'd try to do it yourself, you'd have to use FFI which is a bit awkward (see the gem's code), or call commands like df -B1 and search the strings for your relevant data.
That gem takes the pain away and works nicely.

Testing ActiveRecord validations with RSpec

Validations should be covered by a model's spec.

This card shows how to test an individual validation. This is preferrable to save an entire record and see whether it is invalid.

Recipe for testing any validation

In general any validation test for an attribute :attribute_being_tested looks like this:

  1. Make a model instance (named record below)
  2. Run validations by saying record.validate
  3. Check if record.errors[:attribute_being_tested] contains the expected validation error
  4. Put the attribute into a valid state
  5. Run...

Bundler: Install gems behind a proxy

To install gems Bundler needs to be able to talk to https://api.rubygems.org.

If you are behind a proxy you can use the https_proxy environment variable:

https_proxy=http://myproxy:123 bundle install

Note that if there is no https_proxy env variable, Bundler will also look for a http_proxy env variable.

With Capistrano

Ideally the server you're deploying on exports an https_proxy variable for all shells.

If you don't have control over the server setup, you can also add this to your Capistrano config:
...

NoMethodError: undefined method `cache' for Gem:Module

I got this error when running Rails 2.3 tests for Rails LTS. More stacktrace:

NoMethodError: undefined method `cache' for Gem:Module
    /vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:212:in `each'
    /vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:146:in `to_a'
    /vagrant/rails-2-3-lts-repository/railties/lib/rails_generator/lookup.rb:146:in `cache'
    /opt/vagrant_ruby/lib/ruby/1.8/fileutils.rb:243:in `inject'
    /vagrant/rails-2-3-lts-repository/railties/l...

Showing a custom maintenance page while deploying

Note

The maintenance mode is enabled on all application server as soon as the file /public/system/maintenance.html is present.

Installation

Add this line to your application's Gemfile:

 gem 'capistrano', '~> 3.0'
 gem 'capistrano-maintenance', '~> 1.0'

Add this line to you application's Capfile:

require 'capistrano/maintenance'

Enable task

Present a maintenance page to visitors. Disables your application's web interface by writing a #{maintenance_basename}.html file to each web server. The servers m...

Linux Performance Analysis in 60,000 Milliseconds

You login to a Linux server with a performance issue: what do you check in the first minute?

uptime
dmesg | tail
vmstat 1
mpstat -P ALL 1
pidstat 1
iostat -xz 1
free -m
sar -n DEV 1
sar -n TCP,ETCP 1
top

Also see:

rack-mini-profiler - the Secret Weapon of Ruby and Rails Speed

rack-mini-profiler is a powerful Swiss army knife for Rack app performance. Measure SQL queries, memory allocation and CPU time.

This should probably not be loaded in production (the article recommends otherwise), but this looks like a useful tool.

Unindent HEREDOCs in Ruby 2.3

In Ruby 2.3 you can use <<~ instead of <<- to automatically remove indentation from a HEREDOCs:

str = <<~MESSAGE
  Hello Universe!
  This is me.
             Bye!
MESSAGE

str will now be:

Hello Universe!
This is me.
           Bye!

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

How to encode or decode quoted-printable strings

E-mails are usually encoded using Quoted Printable. Here is how to decode or encode such strings.

You probably know Quoted Printable from e-mail bodies appearing in Rails logs, where =s become =3Ds in URLs, or where long lines are split up and trailed by = after each split.

Decode Quoted Printable

Decoding such strings is actually quite simple using plain Ruby:

"foo=3Dbar".unpack('M')[0]
# => "foo=bar"

Note that unpack will return an array. Our result is the 1st item.
...

Stop using bundle exec

Install this gem and stop using bundle exec or even Geordi's handy b. Yay!

Sidekiq: Problems and Troubleshooting

When using Sidekiq in your application, you must write thread-safe code.

This wiki page also lists gems that are known to be unsafe on threaded applications.
When adding a gem that will also be used by a Sidekiq worker, make sure to confirm it's thread-safe.

Beware ruby's var1 = var2 = "value" multiple assignment

This looks like it is safe to use:

2.2.1 :001 > a = b = "hello world"
"hello world"
2.2.1 :002 > a
"hello world"
2.2.1 :003 > b
"hello world"
2.2.1 :004 > b = " goodbye!"
" goodbye!"
2.2.1 :005 > a
"hello world"
2.2.1 :006 > b
" goodbye!"

But it isn't!

2.2.1 :010 > a = b = "hello world"
"hello world"
2.2.1 :011 > a
"hello world"
2.2.1 :012 > b
"hello world"
2.2.1 :013 > b << " goodbye!"
"hello world goodbye!"
2.2.1 :014 > a
"hello world goodbye!"
2.2.1 :015 > b
"hello world goodbye!"

What is happening when we do `a = b = ...

Upgrade from Ruby 1.8.7 to 2.1.5 – an incomplete guide

I recommend to go straight to 2.1.5+ without intermediate steps. Otherwhise you burden yourself with unnecessary work of encoding problems.

Issues you may encounter:

  • Set the ruby version within your .ruby-version file to 2.1.5
  • Remove gem ruby-debug and use e.g. byebug
  • Remove gem oniguruma
  • Remove gem fastercsv
  • Replace gem mysql with mysql2
  • Update gem capistrano 2.12.0 to ~>2.12 when bound for Ruby 1.8.7 and remove obsolete explicite Gemfile entries for net-scp and net-ssh if present.
  • Update gem `and...

Override Cucumber steps without an ambiguity error

Cucumber raises a Cucumber::Ambiguous if more than one step definitions match a step.

Our new cucumber_priority gem provides a way to mark step definitions as overridable, meaning that they can always be overshadowed by a more specific version without raising an error.

This gem is currently used by spreewald and cucumber_factory.

Marking step definiti...

Defining and calling lambdas or procs (Ruby)

Ruby has the class Proc which encapsulates a "block of code". There are 2 "flavors" of Procs:

  • Those with "block semantics", called blocks or confusingly sometimes also procs
  • Those with "method semantics", called lambdas

lambdas

They behave like Ruby method definitions:

  • They are strict about their arguments.
  • return means "exit the lambda"

How to define a lambda

  1. With the lambda keyword

    test = lambda do |arg|
      puts arg
    end
    
  2. With the lambda literal -> (since Ruby 1.9.1)
    ...

Git: Issues with Gemfile.lock

When there's a Gemfile.lock in your working directory that you cannot remove by either checkout, reset [--hard], stash, probably Rails' Spring is the culprit and not Bundler itself.

Fix

spring stop

The author of the linked Stackoverflow post supposes Spring re-writes the Gemfile.lock on change to ensure all Spring processes are using the same gem versions. Meh.

How to run a small web server (one-liner)

Sometimes you just want to have a small web server that serves files to test something.

Serve the current directory

On Ruby 1.9.2+ you can do the following ("." for current directory). You might need to gem install webrick on modern Rubies.

ruby -run -ehttpd . -p8000

Python 2.x offers a similar way.

python -m SimpleHTTPServer 8000 .

This is the same way with Python 3.x

python -m http.server

In both cases your web server is single-threaded and will block when large files are being downloaded from you.

WEBrick ...

Gemspecs must not list the same gem as both runtime and development dependency

When you're developing a gem, never list the same dependency as both runtime and development dependency in your .gemspec.

So don't do this:

spec.add_dependency 'activesupport'
spec.add_development_dependency 'activesupport', '~> 2.3'

If you do this, your gemspec will not validate and modern versions of Bundler will silently ignore it. This leads to errors like:

Could not find your-gem-0.1.2 in any of the sources

What to do instead

If you want to freeze a different version of a dependency for your t...

Ruby: How to update all values of a Hash

There are many solutions, but a very concise one is this:

hash.merge!(hash) do |key, old_value, new_value|
  # Return something
end

The block of merge! will be called whenever a key in the argument hash already exists in the base hash. Since hash is updated with itself, each key will conflict and thus allow you to modify the value of each key to whatever you like (by returning old_value you'd get the behavior of Rails' reverse_merge!, by re...

Count number of existing objects in Ruby

Sometimes you want to know exactly how many objects exist within your running Ruby process. Here is how:

stats = {}
ObjectSpace.each_object  {|o| stats[o.class].nil? ? stats[o.class] = 0 : stats[o.class] += 1 }; stats

=> {String=>192038, Array=>67690, Time=>2667, Gem::Specification=>2665, Regexp=>491, Gem::Requirement=>16323, Gem::StubSpecification=>2665, ...}

Maybe you want to sort it like this:

stats.sort_by {|k,v| v }

About Ruby's conversion method pairs

Ruby has a set of methods to convert an object to another representation. Most of them come in explicit and implicit flavor.

explicit implicit
to_a to_ary
to_h to_hash
to_s to_str
to_i to_int

There may be even more.

Don't name your methods like the implicit version (most prominently to_hash) but the like the explicit one.

Explicit conversion

Explicit conversion happens when requesting it, e.g. with the splat opera...