Chrome DevTools: Quick Bite - Store Element in Global Variable

tl;dr

In the Elements tab in the Chrome DevTools you can right click on an element and select Store as global variable.

Example

Image

ActiveType::Object: Be careful when overriding the initialize method

Background:

ActiveType::Object inherits from ActiveRecod::Base and is designed to behave like an ActiveRecord Object, just without the database persistence.

Don't remove any of the default behavior of the initialize method!

If you have a class which inherits from ActiveType::Object and you need to override the #initialize method, then you should be really careful:

  • Always pass exactly one attribute. ActiveRecod::Base objects really want to get their arguments processable as keyword arguments. Don't change the syntax, or y...

Temporary solution for connection errors with rubygems

The problem

If you're experiencing that your bundle install command fails with an error message like this, rubygems.org might have issues with their ipv6 connectivity:

$ bundle install
Fetching source index from https://rubygems.org/

Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from https://rubygems.org/ due to underlying error <timed out (https://rubygems.org/specs.4.8.gz)>

The (a little bit dirty) possible solution

If that's actually the case, then you can try to deprioritize the ipv...

Debug flaky tests with an Unpoly observeDelay

The problem

Unpoly's [up-observe], [up-autosubmit] and [up-validate] as well as their programmatic variants up.observe() and up.autosubmit() are a nightmare for integration tests.

Tests are usually much faster than the configured up.form.config.observeDelay. Therefore, it may happen that you already entered something into the next field before unpoly updates that field with a server response, discarding your changes.

The steps I wait for active ajax requests to complete (if configured) and capybara-lockstep can catch some ...

Rails: Validations of Dates, Numerics and Strings with ComparisonValidator

tl;dr

Since Rails 7+ you can use ComparisonValidator for validations like greater_than, less_than, etc. on dates, numerics or strings.

Example

We have a model for booking a trip. This model has mandatory attributes to enforce dates for the start and the end.

# == Schema Information
#
# start_date :date
# end_date   :date
# ...

class TripBooking < ApplicationRecord
  validates :start_date, presence: true
  validates :end_date, presence: true
end

These validations are enough. We also want to ensure, th...

Careful when using Time objects for generating ETags

You can use ETags to allow clients to use cached responses, if your application would send the same contents as before.

Besides what "actually" defines your response's contents, your application probably also considers "global" conditions, like which user is signed in:

class ApplicationController < ActionController::Base

  etag { current_user&.id }
  etag { current_user&.updated_at }

end

Under the hood, Rails generates an ETag header value like W/"f14ce3710a2a3187802cadc7e0c8ea99". In doing so, all objects from that etagge...

Rules of thumb against flaky specs

Here are a few common patterns that will probably lead to flaky specs. If you notice them in your specs, please make sure that you have not introduced a flaky spec.

Using RSpec matchers

One rule of thumb I try to follow in capybara tests is using capybara matchers and not plain rspec matchers.

One example:

visit(some_page)
text_field = find('.textfield')
expect(text_field['value']).to match /pattern/

This can work, but is too brittle and flaky. match will not retry or synchronize the value of text_field.

The equivale...

RubyMine: Find and Replace with Regex (Capture Groups and Backreferences)

tl;dr

In RubyMine you can use find and replace with capture groups (.*?) and backreferences $1 (if you have several groups: $[Capture-Group ID]).
Named captures (?<text>.*) are also supported.

Examples

Replace double quotes with single quotes

If you want to replace double quotes with single quotes, replacing every " with a ' is prone to errors. Regular expressions can help you out here.

  1. Open find and replace
  2. Activate the regex mode (click on the .* icon next to the "find" field).
  3. Fill in f...

SEO: The subtle differences of robots.txt disallow vs meta robots no-index

The robots.txt file and <meta name="robots"> HTML tag can be used to control the behavior of search engine crawlers. Both have different effects.

robots.txt

Marking a URL path as "disallowed" in robots.txt tells crawlers to not access that path.

robots.txt is not a guarantee for exclusion from search engine results.

A "disallowed" URL might be known from an external link, and can still be displayed for a matching search.
Example: even if /admin is disallowed in robots.txt, `/admin/som...

Prefer using Dir.mktmpdir when dealing with temporary directories in Ruby

Ruby's standard library includes a class for creating temporary directories. Similar to Tempfile it creates a unique directory name.

Note:

  • You need to use a block or take care of the cleanup manually
  • You can create a prefix and suffix e.g. Dir.mktmpdir(['foo', 'bar']) => /tmp/foo20220912-14561-3g93n1bar
  • You can choose a different base directory than Dir.tmpdir e.g. `Dir.mktmpdir('foo', Rails.root.join('tmp')) => /home/user/rails_example/tmp/foo20220912-14...

Rails: Comparison of Dates - before? and after?

tl;dr

Since Rails 6+ you can use before? and after? to check if a date/time is before or after another date/time.

Example

christmas = Date.parse('24.12.2022')
date_of_buying_a_gift = Date.parse('12.12.2022')

date_of_buying_a_gift.before?(christmas)
# => true
# Now you are well prepared for Christmas!! ;)

date_of_buying_a_gift = Date.parse('26.12.2022')

date_of_buying_a_gift.after?(christmas)
# => true
# Now you are too late for christmas! :(

Hint

If you want to check if a date/time is between to ot...

Careful: `fresh_when last_modified: ...` without an object does not generate an E-Tag

To allow HTTP 304 responses, Rails offers the fresh_when method for controllers.

The most common way is to pass an ActiveRecord instance or scope, and fresh_when will set fitting E-Tag and Last-Modified headers for you. For scopes, an extra query is sent to the database.

fresh_when @users

If you do not want that magic to happen, e.g. because your scope is expens...

Rails: Custom validator for "only one of these" (XOR) presence validation

For Rails models where only one of multiple attributes may be filled out at the same time, there is no built-in validation.

I've seen different solutions in the wild, each with different downsides:

  • Private method referenced via validate: works, but is barely portable and clutters the model.
  • Multiple presence validations with "if other is blank" each: looks pretty, but is incorrect as it allows both values to be filled in; also the error messages for a blank record are misleading.

Here is a third option: Write a custom validator to ...

JSON APIs: Default design for common features

When you build a JSON API you need to come up with a style to represent attributes, pagination, errors or including associated objects. Instead of reinventing the wheel, you may reuse successful API designs.

JSON API

JSON:API specifies common features found in most JSON APIs, like pagination, ordering and nested resources. The spec looks very similar to how one would build an API with Rails and uses similar patterns. Even if you don't plan on supporting the whole spec, it can still make sense to know how th...

Creating a Rails application in a single file

Greg Molnar has written a neat article about creating a single-file Rails app.
This is not meant for production use but can be useful to try things out, e.g. when hunting down a bug or embedding a Rails app into the tests of a gem.

What you do is basically:

  1. Put everything (gems, application config, database migrations, models, controllers) into a single .ru file, like app.ru.
  2. Run it via rackup app.ru. (Hint: if your file is called config.ru, you can just run `rac...

Yarn: Use yarn-deduplicate to cleanup your yarn.lock

Note

Use yarn dedupe in Yarn v2+: https://yarnpkg.com/cli/dedupe

This package only works with Yarn v1. Yarn v2 supports package deduplication natively!

A duplicate package is when two dependencies are resolved to a different version, even when a single version matches the range specified in the dependencies. See the Deduplication strategies section for a few examples.

Yarn is stupid, so it can happen that there are several version of the same package in your bundle, although one would fulf...

CSS: :is() pseudo selector

tl;dr

The :is() pseudo selector - specificity of its most specific argument - matches against a comma-separated list of selectors.

Example

Compound selectors like ...

.datepicker .prev, .datepicker .next, .datepicker .switch
  padding-bottom: 1rem

ul li, ol li
  list-style-type: none

can be simplified by using the :is() pseudo selector ...

.datepicker :is(.prev, .next, .switch)
  padding-bottom: 1rem

:is(ul, ol) li
  list-style-type: none

Hint

The specificity of :is() is equals t...

CSS: :where() pseudo selector

tl;dr

The :where() pseudo selector - zero specificity - matches against a comma-separated list of selectors.

Example

Compound selectors like ...

.datepicker .prev, .datepicker .next, .datepicker .switch
  padding-bottom: 1rem

ul li, ol li
  list-style-type: none

can be simplified by using the :where() pseudo selector ...

.datepicker :where(.prev, .next, .switch)
  padding-bottom: 1rem

:where(ul, ol) li
  list-style-type: none

Hint

The specificity of :where() is always zero!

I...

Generating and streaming ZIP archives on the fly

When your Rails application offers downloading a bunch of files as ZIP archive, you basically have two options:

  1. Write a ZIP file to disk and send it as a download to the user.
  2. Generate a ZIP archive on the fly while streaming it in chunks to the user.

This card is about option 2, and it is actually fairly easy to set up.

We are using this to generate ZIP archives with lots of files (500k+) on the fly, and it works like a charm.

Why stream downloads?

Offering downloads of large archives can be cumbersome:

  • It takes time to b...

A short overview of common design patterns implemented within Rails

The linked content includes a few design patterns implemented with Ruby on Rails.

What is the card indented to achieve?

  • You can use the pattern names for code reviews, so all parties know with only a few words which change is requested. Example: "Please use a form object here"
  • You can learn about new code patterns
  • You should read the sections "Advantages of using design patterns" and "Disadvantages of using design patterns in a wrong way", since design patterns do not replace good code

Included Design Patterns: Service, Value objec...

makandra tech survey - results

These are the results of the "personal tech stack survey". I've included only the most popular mentions, maybe it can help you find one or two useful tools for your own usage.

Desktop environment

pie title Desktop environment
    "Gnome" : 16
    "i3": 2
    "sway": 2
    "awesome": 1
    "bspwm": 1
    "mate": 1
    "xfce": 1

Gnome dominates (unsuprising, it's the Ubuntu default), but quite a few people use tiling window managers, most popular i3 and the mostly i3-compatible [sway](https://swaywm....

CSS: The inset CSS shorthand

The inset CSS property is a shorthand that corresponds to the top, right, bottom, and/or left properties. It has the same multi-value syntax of the margin shorthand.

Example

<div class="outer">
  <div class="inner">
    Some text
  </div>
</div>
.outer {
  background-color: cyan;
  position: relative;
  width: 500px;
  height: 500px;
}

Top, right, bottom and left

https://jsfiddle.net/jqx68wem/

.inner {
  background-color: darkCyan;
  position: absolute;
  top: 10px;
  right: 10px;
  bottom: 10p...

PostgreSQL: How to show database size

SELECT pg_size_pretty(pg_database_size('some-database'));

Example

SELECT pg_size_pretty(pg_database_size('cards_p'));
----------------
 13 GB
(1 row)
SELECT pg_database_size('cards_p');
 pg_database_size 
------------------
      13524832927
(1 row)

Related

Double loading issue with Ruby default gems

Ruby includes many standard gems that are bundled into the Ruby installation. Here is an example for the gem strscan that will be displayed as default:

gem list strscan     

*** LOCAL GEMS ***

strscan (default: 3.0.1)

It is still possible to have newer version of a gem installed beside the default version:

gem install strscan  
Fetching strscan-3.0.3.gem
Building native extensions. This could take a while...
Successfully installed strscan-3.0.3
1 gem installed
gem list strscan   

*** LOC...