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

Debugging your Webpack build time with Speed Measure Plugin

If your Webpack build is slow, you can use the Speed Measure Plugin for Webpack to figure out where time is being spent.
Note that at time of writing, Webpack 5 seems unsupported. It works on Webpack 4, though.

Wire it into your application as described in the library's documentation:

  1. Hook into your environment file, e.g. config/webpack/development.js and instead of exporting your Webpack config,...
Repeats

The Ruby Object Model

In Ruby (almost) everything is an Object. While this enables a lot of powerful features, this concept might be confusing for developers who have been programming in more static languages, such as Java or C#. This card should help understanding the basic concepts of Ruby's object model and how things behave.


Usage of objects in Ruby

When working with objects in Ruby, you might think of a "container" that holds metadata, variables and methods. Metadata describes stuff like the object's class or its object_id whi...

Run code before or after an existing Rake task

Before

To run additional code before an existing Rake tasks you can add a dependency like this:

task :before_task do
  # runs before :existing_task
end

Rake::Tasks[:existing_task].enhance [:before_task]

The new dependency will be called after all existing dependencies.

After

To run additional code after an existing Rake tasks, pass a block to enhance:

Rake::Tasks[:existing_task].enhance do
  # runs after :existing task
end

Webpacker: Loading code on demand

Sometimes you want to load code on demand. For instance, when a a large library is only used on a single screen, this library should only be loaded for that screen. It should not blow up the bundle size for all screens.

You can load code on demand by using import() as a function (with parentheses) instead of using it as a keyword import (without parentheses). The import() function returns a promise with the exported variables:

let exports = await import('large-library')

console.log("A named export is ", exports.exportedName)
c...

When does Webpacker compile?

Webpack builds can take a long time, so we only want to compile when needed.

This card shows what will cause Webpacker (the Rails/Webpack integration) to compile your assets.

When you run a dev server

While development it is recommended to boot a webpack dev server using bin/webpack-dev-server.

The dev server compiles once when booted. When you access your page on localhost before the initial compilation, the page may load without assets.

The ...

Linked contentRepeats

Protected and Private Methods in Ruby

In Ruby, the meaning of protected and private is different from other languages like Java. (They don't hide methods from inheriting classes.)

private

Private methods can only be called with implicit receiver. As soon as you specify a receiver, let it only be self, your call will be rejected.

class A
 
  def implicit
    private_method
  end
  
  def explicit
    self.private_method
  end
  
  private
  
  def private_method
    "Private called"
  end
  
end

...

Linux: Using grep with a regular expression

You can use three different versions of the regular expression syntax in grep:

  • basic: -G
  • extended: -E(POSIX)
  • perl: -P (PCRE)

Difference between basic and extended:

In basic regular expressions the meta-characters '?', '+', '{', '|', '(', and ')' loose their special meaning; instead use the backslashed versions '?', '+', '{', '|', '(', and ')'.

Difference between extended (POSIX) and perl (PCRE): E.g. \d is not supported in POSIX.

This g...

Repeats

How to iterate over an Enumerable, returning the first truthy result of a block ("map-find")

Ruby has Enumerable.find(&block), which returns the first item in the collection for which the block evaluates to true.

first_post_with_image = posts.find do |post|
  post.image
end

However, sometimes it's not the item you're interested in, but some value depening on it – e.g. the value the block evaluated to. You could first map the collection and then take the first truthy value, but this way you need to process the whole collection twice:

first_image_url = posts.map(&:image).find(&:present?).url

If the mapping ...

Linked content

Limiting GitLab CI runner to specific branches or events

Use rules to include or exclude jobs in pipelines.

Rules are evaluated in order until the first match. When a match is found, the job is either included or excluded from the pipeline, depending on the configuration. The job can also have certain attributes added to it.

rules replaces only/except and they can’t be used together in the same job. If you configure one job to use both keywords, the linter returns a key may not be used with rules error.

GitLab 12.3 introduced rules. You can use them in your .gitlab-ci.yml in your proj...

Repeats

Clean code: Avoiding short versions in command options

This card is a general reminder to avoid the short version of a command option in shared code. It's much easier to understand a command and search for an option when it's written out.

You can still use the short version of the options in your own terminal or in code snippets that are more useful when they are very compact. For the latter case you often see a description of the command options one line below e.g. in posts on stackoverflow.

Example good (in code):

/usr/bin/gpg --output password.txt --decrypt password.txt.gpg

...

Bundler: Packaging gems into the git repository (offline installation)

Installing gems on a server that has no access to the internet (especially rubygems.org) requires to bundle the gems into the repository itself. This requires to adjust the bundle config in the repository.

  1. Create a file .bundle/config with the following content.
---
BUNDLE_PATH: "vendor/"
BUNDLE_DISABLE_SHARED_GEMS: "true"
  1. Change your .gitignore.
# Make sure to check in .bundle
# /.bundle/

/vendor/ruby
  1. Run bundle package and commit the changes together with all gems in vendor/cache/.

Afterwards you c...

How to generate and test a htpasswd password hash

Generate a password

htpasswd -Bn firstname.lastname

This will ask you for a password and use bcrypt (-B, more secure) and print the output to stdout (-n).

Check if password matches the hash

You'll first have to write the password hash to a file:

echo firstname.lastname:$2y$05$4JXxd2GM/J2...9c3KJmFS > htpass_test

Check, if it is correct:

htpasswd -v htpass_test firstname.lastname

You probably should not use the -b switch to read the password from the command line as the password will then be visible...

Repeats

How to push to Git without running CI on GitLab CI, GitHub Actions, or Travis CI

If a project ist configured to spawn CI runners for tests or deployment when pushing to the Repo, a habit of pushing WIP commits regularly may conflict with that.
Here are two solutions that allow you to keep pushing whenever you feel like it.

Special commit message

To skip a CI run, simply add [ci skip] or [skip ci] to your commit message. Example:

git commit -m "wip authentication [ci skip]"

Git push options (GitLab)

In addition to that, GitLab CI supports Git push options. Instead of changing your commit message, ...

Linked contentRepeats

Geordi hints

Reminder of what you can do with Geordi.

Note: If you alias Geordi to something short like g, running commands gets much faster!
Note: You only need to type the first letters of a command to run it, e.g. geordi dep will run the deploy command.

geordi deploy

Guided deployment, including push, merge, switch branches. Does nothing without confirmation.

geordi capistrano

Run something for all Capistrano environments, e.g. geordi cap deploy

geordi setup -t -d staging

When you just c...

Repeats

Do not pass an empty array to ActiveRecord.where when using NOT IN

Be careful with the Active Record where method. When you accidentally pass an empty array to the where method using NOT IN, you probably will not get what you expected:

User.where("id NOT IN (?)", [])
=>  SELECT `users`.* FROM `users` WHERE (id NOT IN (NULL))

Even though you might expect this to return all records, this actually results none.

Never use the expression id NOT IN (?) without taking care of this case! See below some workarounds.

Rails < 4

Rails < 4 does not provide a pretty workaround.

ids = []

...
Linked contentRepeats

How to write a good changelog

We want to keep a changelog for all gems we maintain. There are some good practices for writing a changelog that adds value, please stick to these.

  • Add a notice to the README's contribute section about the changelog
  • For every release update the changelog
  • Note the date format yyyy-mm-tt

What is a changelog?

A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of a project.

Why keep a changelog?

To make it easier for users and...

Emulating document.currentScript in old browsers

When you need the DOM node of a <script> tag (e.g. to read extra attributes, or to modify the DOM near it), you can usually reference it via document.currentScript.
However, document.currentScript is unsupported in ancient browsers, like Internet Explorer 11 or wkhtmltopdf's Webkit engine.

If you are not running async scripts, you can easily polyfill it:

document.scripts[document.scripts.length - 1]

It works because document.scripts grows with each <script> tag that was evaluated.
That is also the reason why th...

This website uses short-lived cookies to improve usability.
Accept or learn more