has_one association may silently drop associated record when it is invalid

This is quite an edge case, and appears like a bug in Rails (4.2.6) to me.

Update: This is now documented on Edgeguides Ruby on Rails:

If you set the :validate option to true, then associated objects will be validated whenever you save this object. By default, this is false: associated objects will not be validated when this object is saved.

Setup

# post.rb
class Post < ActiveRecord::Base
  has_one :attachment
end
# attachm...

ActiveRecord autosave

When ActiveRecord child objects are autosaved in Rails.

Ruby's default encodings can be unexpected

Note: This applies to plain Ruby scripts, Rails does not have this issue.

When you work with Ruby strings, those strings will get some default encoding, depending on how they are created. Most strings get the encoding Encoding.default_internal or UTF-8, if no encoding is set. This is the default and just fine.

However, some strings will instead get Encoding.default_external, notably

  • the string inside a StringIO.new
  • some strings created via CSV
  • files read from disk
  • strings read from an IRB

Encoding.default_external d...

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

Download Ruby gems without installing

You can download .gem files using gem fetch:

gem fetch activesupport consul

This will produce files like active-support-5.0.0.gem and consul-0.12.1.gem in your working directory.

Dependencies will not be downloaded.

Ruby 2.3.0 has a safe navigation operator

As announced before, Ruby has introduced a safe navigation operator with version 2.3.0. receiver&.method prevents NoMethodErrors by intercepting method invocations on nil.

user = User.last
user&.name # => "Dominik"
# When there is no user, i.e. user is nil:
user&.name # => nil

This might remind you of andand, and indeed it behaves very similar. The only difference is in handling of `fa...

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

virsh reload xml config file

If you have made any changes to a libvirt xml config file you have to reload is. One way is to reload the whole libvirtd service. But you can just reload corresponding domain xml too:

$ virsh define foo.xml

Ruby 2.3 brings Array#dig and Hash#dig

#dig lets you easily traverse nested hashes, arrays, or even a mix of them. It returns nil if any intermediate value is missing.

x = {
  foo: {
    bar: [ 'a', { baz: 'x' } ]
  }
}

x.dig(:foo, :bar) # => [ 'a', { baz: 'x' } ]
x.dig(:foo, :bar, 1, :baz) # => "x"
x.dig(:foo, :wronk, 1, :baz) # => nil

There is a tiny gem that backports this.

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

object-fit polyfill by lazysizes

All new browsers support the new object-fit CSS property. It allows to specify how an element behaves within its parent element and is intended for images and videos. The most useful values are contain (fit-in) and cover (crop).

Unfortunately, IE does not support this yet. However, if you're already using lazysizes, you can use its object-fit polyfill!

Usage

In your Javascript manifest, require them like this:

#= require plugins/object-fit/ls.obj...

request_store: Per-request global storage for your Rails app

Ever needed to use a global variable in Rails? Ugh, that's the worst. If you need global state, you've probably reached for Thread.current.

When you're using Thread.current, you must make sure you're cleaning up after yourself. Else, values stored in one request may be available to the next (depending on your server). request_store wipes all data when a request ends and makes per-request global storage a no-brainer. Internally, it's using Thread.current with a Hash in a simple middleware.

Example: Remembering all currently a...

Using Responsive Images

This card has become a blog post!

Web font rendering on Macs

Macs render fonts bolder than they are, especially on dark background. This can be fixed by configuring the font smoothing:

body
  -webkit-font-smoothing: antialiased
  -moz-osx-font-smoothing: grayscale

You should do this on every project, all the time.

Stubbing terminal user input in RSpec

Reading user input in console applications is usually done using Kernel#gets. Stubbing that can be a bit hairy.

When your code expects user input, you can not say Kernel.stub(gets: 'user input'). This will have no effect because of reasons.

Instead, you need to know which class will call gets. For example:

described_class.any_instance.stub(gets: 'user input')

If you do not know where gets is called, you can try something like this:

Object.any_instance.stub(gets: 'user input')

Any instance of an object should...

Testing terminal output with RSpec

When testing Ruby code that prints something to the terminal, you can test that output.
Since RSpec 3.0 there is a very convenient way to do that.

Anything that writes to stdout (like puts or print) can be captured like this:

expect { something }.to output("hello\n").to_stdout

Testing stderr works in a similar fashion:

expect { something }.to output("something went wrogn\n").to_stderr

Hint: Use heredoc to test multi-line output.

expect { something }.to output(<<-MESSAGE.strip_heredoc).to_stdout...

HAML 4+ expands nested element attributes

As you may know, HAML expands data attributes that are given as a hash:

%div{ data: { count: 3 } }
# results in:
<div data-count="3"></div>

However, this also works for any other hash attribute. Consider an Angular directive or an Unpoly compiler that is configured by several attributes. Usually you'd prefix them with the directive/compiler name so it gets clear where the attribute belongs. With HAML, this is easy to build:

%...

About IE's Compatibility mode

IE has a "Compatibility Mode" for old browsers. You can keep IE from offering it (and fix some other things, too) by adding this meta tag to your <head>:

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

Or in Haml:

%meta(http-equiv="X-UA-Compatible" content="IE=Edge")

However, there are some things you need to bear in mind:

  • X-UA-Compatible is ignored unless it's present inside the first 4k of you page. If you put it somewhere in the bottom of your head section (or in the body) move it to top. The best place for ...

How to test whether your device has a true Retina display

The linked site hosts a simple test. It shows two images with narrow vertical/horizontal lines. The more they resemble each other, the more Retina your display is.

instance_eval behaves different in Ruby 1.8 and Ruby 1.9, use instance_exec instead

In Ruby 1.9, instance_eval calls the block the with receiver as the first argument:

  • In Ruby 1.8, receiver.instance_eval(&block) calls block.call()
  • In Ruby 1.9, receiver.instance_eval(&block) calls block.call(receiver)

This will blow up in your face in Ruby 1.9, where a lambda crashes when it is called with a different number of arguments:

wrong number of arguments (1 for 0) (ArgumentError)

Forget that instance_eval ever existed. Use instance_exec instead, which behaves consistently across all Rubies.

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

...

Rails Env Widget

Have you ever mistaken one Rails environment for another? The attached helper will help you to never do it again.

Save the attached file to app/helpers/ and use the widget in your layout like this:

%body
  = rails_env_widget unless Rails.env.production?

It'll render a small light gray box in the top left corner of your screen, containing the current Rails environment. On click, it'll disappear. Actually, it has the same UX as our Query Diet widget.

Thunderbird add-on to manually sort accounts and folders

This extension allows you to manually sort (order) your folders in the folder pane of Thunderbird or automatically sort them, but in a better way. This extension also allows you to re-order accounts in the folder pane.

Ruby: Converting UTF-8 codepoints to characters

Converting string characters to or from their integer value (7-bit ASCII value or UTF-8 codepoint) can be done in different ways in Ruby:

  • String#ord or String#unpack to get character values
  • Integer#chr or Array#pack to convert character values into Strings

Character values to Strings

Integer#chr

To get the character for a 7-bit ASCII value or UTF-8 codepoint (0-127) you can use Integer#chr:

116.chr
# => "t"

To get a character for values larger than 127, you need to pass the encoding. E.g. to get codepoint 25...