3921 cards

How to: "git log" with renamed files

While renaming a file sometimes feels like "dropping its history", that is not true: Just use git log --follow on renamed files to access their full history.

Given a file "bar" that was previously named "foo":

touch foo
git add foo
git commit -m "Add foo"
mv foo bar
git add bar
git commit -m "Rename foo to bar"

git log bar

commit adc8e6a05b65355359c4e4618d6af0ed8f8b7f14 (HEAD -> git-follow)
Author: Michael Leimstaedtner <makmic@makandra.de>
Date:   Wed May 12 08:49:37 2021 +0200

    Rename foo to bar

git lo...

Repeats

How to create memory leaks in jQuery

jQuery doesn't store information about event listeners and data values with the element itself. This information is instead stored in the global $.cache object. Every time you add an event listener or data value to a jQuery object, $.cache gains another entry.

The only way that a $.cache entry gets deleted is when you call remove() on the element that put it there!

Since cache entries also have a pointer back to the element that spawned them, it is easy to create DOM elements that can never be garbage-collected.

Below are ...

RestClient / Net::HTTP: How to communicate with self-signed or misconfigured HTTPS endpoints

Occasionally, you have to talk to APIs via HTTPS that use a custom certificate or a misconfigured certificate chain (like missing an intermediate certificate).

Using RestClient will then raise RestClient::SSLCertificateNotVerified errors, or when using plain Net::HTTP:

OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

Here is how to fix that in your application.

Important: Do not disable certificate checks for production. The interwebs are full of people say...

Repeats

Rspec: how to ensure a method is called on a record that is not yet created

rspec >= 3.1 brings a method and_wrap_original. It seems a bit complicated at first, but there are use cases where it helps to write precise tests. For example it allows to add expectations on objects that will only be created when your code is called.

If you have older rspec, you could use expect_any_instance_of, but with the drawback, that you can't be sure if it really was the correct instance which got the message.


The example model uses different validators based on a flag:

class MyModel < ApplicationRecord

  # ...

  d...
Repeats

7 Rules for Creating Gorgeous UI

A great two-part article about various hacks you can use to create great-looking screen designers when you're not a designer.

Part 1 contains:

  • Light comes from the sky
  • Black and white first
  • Double your whitespace

Part 2 contains:

  • Learn the methods of overlaying text on images
  • Make text pop— and un-pop
  • Only use good fonts
  • Steal like an artist
Linked contentRepeats

Heads up: Sidekiq per default silently fails when retries are exhausted!

For Sidekiq to be able to retry your jobs it has to be able to catch errors that occur while a job is executed.

Per default, Sidekiq will not raise / notify you if the retry count is exhausted. It will only copy the job to the dead queue (see wiki).

If you want to get notified, you have to implement it in your worker explicitly with a sidekiq_retries_exhausted-block, e.g. like this:

class DownloadWorker
  include Sidekiq::Worker

  # Import jobs are retried a few times wi...
Repeats

Regular tasks for long-running projects

When projects run for many years, they require special regular maintenance to stay fresh. This kind of maintenance is usually not necessary for small or quick projects, but required to keep long-running projects from getting stale.

You should be able to fit this into a regular development block.

Quarterly

Check which libraries need updating

As time goes by, libraries outdate. Check your software components and decide if any of it needs an update. Your main components (e.g. Ruby, Rails, Angular) should always be reasonably up to ...

Ruby: Fixing strings with invalid encoding and converting to UTF-8

When dealing with external data sources, you may have to deal with improperly encoded strings.
While you should prefer deciding on a single encoding with the data-providing party, you can not always force that on external sources.
It gets worse when you receive data with encoding declaration that does not reliably fit the accompanying string bytes.

Here is a Ruby class that helps converting such strings to a proper encoding.
Note that it tries several approaches of changing the encoding. **This is not a silver bullet and may or may not work...

Disabling client caching with Cache-Control: no-store

Browsers usually cache website content in order to provide the user with faster responses. Examples are returning to a website using the "Back" button, or reopening a browser and restoring previous tabs.

However, there are applications where this kind of client caching produces annoying results: a time tracking tool may show a wrong clock-in state, or an SPA todo app may display an outdated list. In these cases, client caching should be disabled.

In order to prevent client caching, set a Cache-Control header of no-store. This tells _...

Pre-releasing an npm package

You can publish pre-release versions of an npm package.

Naming convention for pre-release versions

An npm package must use Semantic Versioning's naming convention for its version. In Semantic Versioning, the version number and pre-release identifier (like rc1) must be separated by a dash, like this:

  • 1.0.0-rc1
  • 2.3.0-alpha2
  • 3.0.0-beta3

Publishing to a pre-release tag

npm packages have multiple "current" releases, identified by "tags". The default tag is latest. It is expected to contain the la...

Pre-releasing a Ruby gem

When a Ruby version gem has a letter in its version number, it is considered a pre-release:

  • 1.0.0.rc1
  • 2.3.0.alpha2
  • 3.0.0.beta3
  • 4.0.0.pre.rc2

Even if a pre-release gem has the highest version number, it is never installed unless the user explictily requested the version:

gem install foobar --version="=2.3.0.alpha2"

Also bundle update will never update a stable version to a pre-release version unless the user explicitly requests it in the Gemfile:

gem 'foobar', '=2.3.0.alpha2'

A note on Semanti...

How to use ActiveSupport Concerns with dynamic relations

The usual way to build a relation in a ActiveSupport::Concern is this:

module MyModule
  extend ActiveSupport::Concern

  included do
    scope :disabled, -> { where(disabled: true) }
  end

end

However, if you have a association with a polymorphic model, where you have to select based on the kind of record, using included like this will not produce the wanted results:

module MyModule
  extend ActiveSupport::Concern

  included do
    has_many :tasks,
      ->...
Linked content

RubyMine: How to exclude single files

In RubyMine folders can be excluded from search, navigation etc. by marking it as excluded. You might sometimes wish to exclude single files, too. An example could be .byebug_history which is located in the project root directory.

Single files can be excluded by pattern in the Settings:

  1. In the Settings/Preferences dialog Ctrl+Alt+S, go to Project structure
  2. In the Exclude files field, type the masks that define the names of files and folders to be exclu...
Linked contentRepeats

How to tell ActiveRecord how to preload associations (either JOINs or separate queries)

Remember why preloading associations "randomly" uses joined tables or multiple queries?

If you don't like the cleverness of this behavior, you can explicitely tell ActiveRecord how to preload associations with either JOINs or separate queries:

  • joins will join the given association so you can order or add conditions.

    User....
    
Linked contentRepeats

Custom error messages in RSpec or Cucumber steps

Sometimes you have a test expectation but actually want a better error message in case of a failure. Here is how to do that.

Background

Consider this test:

expect(User.last).to be_present

In case of an error, it will fail with a not-so-helpful error message:

expected present? to return true, got false (Spec::Expectations::ExpectationNotMetError)

Solution

That can be fixed easily. RSpec expectations allow you to pass an error message like this:

expect(User.last).to be_present, 'Could not find a user!'

Now your t...

Repeats

ActiveRecord: When aggregating nested children, always exclude children marked for destruction

When your model is using a callback like before_save or before_validation to calculate an aggregated value from its children, it needs to skip those children that are #marked_for_destruction?. Otherwise you will include children that have been ticked for deletion in a nested form.

Wrong way

class Invoice
  has_many :invoice_items
  accepts_nested_attributes_for :invoice_items, :allow_destroy => true # the critical code 1/2
  before_save :calculate_and_store_amount                              # the critical code 2/...

Carrierwave: Using a nested directory structure for file system performance

When storing files for lots of records in the server's file system, Carrierwave's default store_dir approach may cause issues. Here is a simple solution that scales for a long while.

The default storage directory from the Carrierwave templates looks like so:

class ExampleUploader < CarrierWave::Uploader::Base
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end
end

If you store files for 500k records, that store_dir's parent directory will have 500k sub-directories which will cause s...

Repeats

Carrierwave: How to remove container directories when deleting a record

When deleting a record in your Rails app, Carrierwave automatically takes care of removing all associated files.
However, the file's container directory will not be removed automatically. If you delete records regularly, this may be an annoyance.

Here is a solution which was adapted from the Carrierwave GitHub wiki and cleans up any empty parent directories it can find.

class ExampleUploader < CarrierWave...
This website uses short-lived cookies to improve usability.
Accept or learn more