It's OK to put block elements inside an <a> tag
In general, you should not put a block element inside an inline element. So don't do this:
<span>
<div>text</div>
</span>
The browser will think you wrote invalid HTML by accident, and will sometimes reorder elements silently.
There is one notable exception: It's OK to wrap block elements in a <a>
tag in HTML5 (not 4). The spec says:
The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long ...
IE11: Trigger native mouse events with Javascript
The attached Coffeescript helper will let you create mouse events:
$element = $('div')
Trigger.mouseover($element)
Trigger.mouseenter($element)
Trigger.mousedown($element)
Trigger.mouseup($element)
Trigger.mouseout($element)
Trigger.mouseleave($element)
Trigger.click($element)
The dispatched events are real DOM events, which will trigger both native and jQuery handlers.
jQuery's .trigger
is simpler, but will only trigger event handlers that were bound by jQuery's .on
.
Real user actions t...
Let the browser choose the protocol
Use protocol independent URLs whenever possible so that the browser will choose the protocol related to the protocol which the page is delivered with.
Example issues
- When your page is delivered via
https
and you provide a youtube video only viahttp
the most browsers (e.g. Firefox, Chrome) won't display the video. - When you deliver your youtube video via
https://youtu.be/jyElDp98HdI
your test which checks that the embeded video is rendered in the view will fail because your test server doesn't use https
Solution
Let your lin...
Heads up: Byebug has problems with zeitwerk
I encountered a unlucky behavior of byebug 11.1.3 (the most recent version at time of writing) when using it with Rails 6 and it's new autoloading component, zeitwerk. There already is a issue for that, so I hope it will be fixed with a future release.
The following test succeeds:
context 'factories' do
let(:test_case) { FactoryBot.create(:test_case) }
it 'are valid' do
expect(test_case).to be_valid
end
end
But when I did the same in byebug the foll...
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...
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 a global, internal jQuery cache object. Every time you add an event listener or data value to a jQuery object, the jQuery cache gains another entry.
The only way that a jQuery 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-co...
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...
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 time...
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,
->...
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:
- In the Settings/Preferences dialog
Ctrl+Alt+S
, go to Project structure - In the Exclude files field, type the masks that define the names of files and folders to be exclu...
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....
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...
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, because some directories will hold too many entries.
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 some...
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:
- Hook into your environment file, e.g.
config/webpack/development.js
and instead of exporting your Webpackconfig
,...
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::Task[: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::Task[: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 ...
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
...