Cheat Sheet for the modern DOM API
See the attached link for a useful overview of modern (and classic) DOM API methods, like matches
, contains
, append
, cssText
, etc.
You will still need to look up some documentation, e.g. on how to modify a ClassList
, but it's still better than browsing interfaces and superclasses of Element
on MDN without knowing what to look for.
When coming from jQuery, also see the card on JavaScript without jQuery. This card includes a link to [You Don't Need jQuery](https://github.com/nefe/You-Dont-Need-jQuery/blob/maste...
How to debug file system access in a Rails application
It might sometimes be useful to check whether your Rails application accesses the file system unnecessarily, for example if your file system access is slow because it goes over the network.
The culprit might be a library like carrierwave that checks file existence or modification times, whereas your application could determine all this from your database.
Introducing strace
One option it to use strace for this, which logs all system calls performed by a process.
To do this, start your rails server using something like
DISA...
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, ...
Bundler: Enforce consistent platform versions
Some rubygems come in platform-specific versions (i.e. "x86_64-linux") in addition to the usual "ruby" platform. This is often is done for gems with native extensions that want to deliver precompiled binaries for ease of installation. However, there is an issue on some versions of Bundler (at least 2.3.x) that makes it inconsistent which versions of a gem will be installed.
Why this happens
On (very) old versions of Bundler, the Gemfile.lock
could never indicate which version of a gem was installed, i.e. the Gemfile read `nokogiri (1....
Make Nokogiri use system libxml2
The nokogiri gem provides different packages for several platforms. Each platform-specific variant ships pre-built binaries of libxml2
, e.g. x86_64-linux
includes binaries for 64bit Linux on Intel/AMD.
This significantly speeds up installation of the gem, as Nokogiri no longer needs to compile libxml2
.
However, this also means that for each security issue with libxml2
, Nokogiri maintainers have to update their pre-built binaries and release a new version of the gem. Then, you need to update and ...
How to force horizontal panel layout for Chrome
Chrome's developer tools automagically choose vertical or horizontal panel layout, based on their width. You can disable that magic.
In the developer tools, klick the cogwheel icon (or press F1
when focusing the dev tools) to open the settings overlay.
Under "Preferences", in the "Appearance" section, find the "Panel layout" option. Set it to your liking.
Alternatively, press Ctrl+Shift+P and search for "panel layout".
Wat?
Vertical means that the DOM tree is next to the styles/etc panel, like so:
![vertical layout example](https:/...
Capistrano: How to find out which version of your application is currently live
When deploying, Capistrano puts a REVISION
file into your application's release directory. It contains the hash of the commit which was deployed.
If you want to know the currently deployed release, simply SSH to a server and view that file.
$ cat /var/www/my-project/current/REVISION
cf8734ece3938fc67262ad5e0d4336f820689307
Capistrano task
When your application is deployed to multiple servers, you probably want to see a result for all of them.
Here is a Capistrano task that checks all servers with the :app
role.
Simple debounce in vanilla JavaScript
Debouncing a method call delays its execution until after a specified time has passed.
If it's called again before that time has passed, its execution is delayed again.
This technique is commonly used to improve performance when code would be run more often than it needs to.
One example for that are scroll
event handlers in JavaScript: You want to react to a user scrolling, but it's enough to do that when they have stopped scrolling.
Here is a small JavaScript function that you can use for that:
function debounce(callback...
Upgrading RubyGems to the last compatible version
Running gem update --system
will install the latest version of RubyGems. However the latest version might not be compatible with your current version of Ruby.
To install the latest version that is compatible with your Ruby:
- Go to the version history and find the latest compatible version (any Ruby constraint can be found in the right sidebar)
- Append that version to the
update
command. E.g. to install the latest version compatible with Ruby 2:gem update --system 3.4.22
...
Rails: Example on how to extract domain independent code from the `app/models` folder to the `lib/` folder
This cards describes an example with a Github Client on how to keep your Rails application more maintainable by extracting domain independent code from the app/models
folder to the lib/
folder. The approach is applicable to arbitrary scenarios and not limited to API clients.
Example
Let's say we have a Rails application that synchronizes its users with the Github API:
.
└── app
└── models
├── user
│ ├── github_client.rb
│ └── sychronizer.rb
└── user.rb
In this example the app folder ...
Ruby: How to make your ruby library configurable
You might know a few examples, where you configure some library via a block. One example is the Rails configuration:
Rails.application.configure do |config|
config.enable_reloading = false
end
This card describes a simple example on how to make your ruby library configurable.
Example
module FooClient
class Client
class_attribute :config
def self.configure
self.config ||= Configuration.new
yield(config)
end
def test
uri = URI.parse(FooClient::Client.config.endpoint)
Net:...
MySQL will not use indexes if you query the wrong data type
When MySQL refuses to use your index, there's a number of things that you may be doing wrong. One of them might be conditions with improper data types.
An example
For example, let's assume you have a users
table with an email
field (varchar
) which is indexed.
MySQL will use the index when your query is well-formed:
mysql> EXPLAIN SELECT * FROM users WHERE email = 'foo@example.com';
+----+-------------+-------+-------+----------------------+----------------------+---------+-------+------+-------+
| id | select_type |...
Rspec: around(:all) and around(:each) hook execution order
Background
-
before(:all)
runs the block once before all of the examples. -
before(:each)
runs the block once before each of your specs.
Summary
-
around(:suite)
does not exist. -
around(:all)
runs afterbefore(:all)
and beforeafter(:all)
. -
around(:each)
runs beforebefore(:each)
and afterafter(:each)
.
As this is not 100% obvious (and not yet documented) it is written down in this card. In RSpec 3 :each
has the alias :example
and :all
the alias :context
.
Example
RSpec.configure do |config|
...
Ruby: Different ways of assigning multiple attributes
This card is a short summary on different ways of assigning multiple attributes to an instance of a class.
Using positional parameters
Using parameters is the default when assigning attributes. It works good for a small number of attributes, but becomes more difficult to read when using multiple attributes.
Example:
class User
def initialize(salutation, first_name, last_name, street_and_number, zip_code, city, phone_number, email, newsletter)
@salutation = salutation
@first_name = first_name
@last_name = last_nam...
Updated: Migrating from CoffeeScript to ES6
- Simplified setup
- Recommend using eslint to clean up styling
Chrome: disable "Choose your search engine" popup in tests
Fresh Chrome installations now show a "Choose your search engine" popup in Europe. This might make your Cucumber tests fail.
Fortunately there is a flag to disable the popup. Add the following option to your chromedriver setup code:
options.add_argument('--disable-search-engine-choice-screen')
I found this flag in Peter Beverloo's list.
Background: This was experienced locally with google-chrome 127.0.6533.72
. In CI I did not get the popup.
cucumber_factory 1.14 lets you set array fields, has_many associations, numbers without quotes
Setting array columns
When using PostgreSQL array columns, you can set an array attribute to a value with square brackets:
Given there is a movie with the tags ["comedy", "drama" and "action"]
Setting has_many associations
You can set has_many
associations by referring to multiple named records in square brackets:
Given there is a movie with the title "Sunshine"
And there is a movie with the title "...
Customizing Rails error messages for models and attributes
Rails has generic error messages you can define in your locale .yml
files. You may override those application-wide error messages using model or attribute scope like this:
en:
activerecord:
errors:
messages:
invalid: is invalid # used for any invalid attribute in the application
presence: etc
models:
car:
invalid: does not work # used for invalid car attributes
attributes:
driver:
invalid: not allowed to drive # used if the car's driver attribut...
Load order of the environment
Rails 3, 4, 5, 6
config/application.rb
-
config/environment.rb
before theinitialize!
call (we don't usually edit this file) - The current environment, e.g.
environments/production.rb
- Gems
- Vendored plugins
- All initializers in
config/initializers/*.rb
-
config/environment.rb
after theinitialize!
call (we don't usually edit this file) - Your own code from
app
Rails 2
- Code in
config/preinitializer.rb
(if it exists) -
environment.rb
, code above theRails::Initializer.run
blo...
Beware of params with non-string values (nil, array, hash)
Recent rails security updates have shown that people make incorrect assumptions about the possible contents of the params
hash.
Just don't make any! Treat it as what it is: potentially unsafe user input. For example:
/pages/edit?foo= --> params == {:foo => ""}
/pages/edit?foo --> params == {:foo => nil}
/pages/edit?foo[] --> params == {:foo => [nil]} # at least in older rails 3 and in rails 2.x
Be especially wary about stuff like
User.find_by_password_reset_token(params[:password_reset_token])
I...
Ruby blocks: Braces and do/end have different precedence
TL;DR {}
binds stronger than do … end
(as always in Ruby, special characters bind stronger than words)
Demo
✔️ Right way
names = ['bRUce', 'STaN', 'JOlIE']
# Blocks in braces are passed to the rightmost method
print names.map { |name| name.downcase }
print(names.map do |name| name.downcase end) # equivalent
=> ["bruce", "stan", "jolie"]
❌ Wrong way
Avoid the examples below, as you pass at least one block to print and not to the enumerator.
names = ['bRUce', 'STaN', 'JOlIE']
# Blocks in do…end ar...
Tod: A Gem for handling daytime without a date
Tod is a gem for working with daytimes. That's a tuple of (hour, minute second)
without a day, month or year.
Another additional gem?
Thus SQL has a time
datatype for storing time of day in the format hh:mm:ss
, neither Ruby nor Rails themselves offer an elegant way to deal with day times.
Time
and DateTime
both handle daytime values AND calendar date, using them to only store the time of day will end in inconsistent and thus confusing data, e. g. Time.new
will initialize with the current Time in your Timezone, `DateTime.n...
Capistrano: Configure environment specific array attributes
Using Capistrano, we usually have some array configurations in the config/deploy.rb
file, like set :linked_files, %w[config/database.yml]
, so in this case we don't have to manage the database configuration individually on every server.
In a specific case, one of our projects supports sign in by SAML
, but not every deploy target has this feature activated. Here comes a nice handy Capistrano feature, which lets us modify the default configuration for individual env...
Rails I18n scope for humanized attribute names
ActiveModel classes have a class method .human_attribute_name
. This returns a human-readable form of the attribute:
Person.human_attribute_name(:first_name) # => "First name"
By default Rails will use String#humanize
to format the attribute name, e.g. by replacing underscores with spaces and capitalizing the first word. You can configure different translation in your I18n locales, e.g. in config/locales/en.yml
:
en:
activerecord:
attributes...