Running "bundle update" without arguments might break your application
Calling bundle update
(without arguments) updates all your gems at once. Given that many gems don't care about stable APIs, this might break your application in a million ways.
To stay sane, update your gems using the applicable way below:
Projects in active development
Update the entire bundle regularily (e.g. once a week). This ensures that your libraries are up-to-date while it's easy to spot major version bumps which may break the app.
Projects that have not been updated in a while
- [Update a single gem conservatively](htt...
Calling a helper method with the same name as your current partial
Partials always define a local variable with the same name as themselves. E.g. when you are in _recent_users.html.erb
, a local variable recent_users
will be defined and overshadow any helper method that is also called recent_users()
.
If you would like to use a helper method recent_users()
in a partial _recent_users.html.erb
you can say this in the partial template:
<% recent_users = self.recent_users() %>
<% recent_users.each do |user| %>
...
<% end %>
Your database tables should always have timestamps
Whenever you create a table from a database migration, remember to add updated_at
and created_at
timestamps to that table. Without those timestamps, investigating future bug reports will be hell. Always have timestamps.
Adding timestamps to new tables
When you create a table using create_table
, you can add timestamps by using the timestamps
shortcut:
class CreateEpisode < ActiveRecord::Migration
def change
create_table :episodes do |t|
t.string :name
t.timestam...
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...
Fix: esbuild assets are missing after capistrano deploy
Issue: You have an app using jsbundling-rails and esbuild. After deploy, the assets built by esbuild are missing in public/assets.
Solution: Add app/builds
to your git repo (by adding a app/builds/.keep
file).
Something in sprockets is caching paths and refuses to accept files in "unknown" locations.
Fix PNG colors in IE, old Safaris and new Firefoxes
Some browsers render PNG images with color profiles and other shenanigans, some don't.
The cleanest way to have consistent colors across browsers is to convert all your images to a standard color profile, strip the image's original profile and attach the standard profile.
If you can't be bothered to convert color profiles, a quicker (but less effective) method is to remove some PNG chunks from your files.
With Geordi
[Geordi](https://git...
Writing strings as Carrierwave uploads
When you have string contents (e.g. a generated binary stream, or data from a remote source) that you want to store as a file using Carrierwave, here is a simple solution.
While you could write your string to a file and pass that file to Carrierwave, why even bother? You already have your string (or stream).
However, a plain StringIO object will not work for Carrierwave's ActiveRecord integration:
>> Attachment.create!(file: StringIO.new(contents))
TypeError: no implicit conversion of nil into String
This is because Carrierwav...
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
The Easiest Way to Parse URLs with JavaScript
A very clever hack to parse a structured URL object is to create a <a>
element and set its href
to the URL you want to parse.
You can then query the <a>
element for its components like schema, hostname, port, pathname, query, hash:
var parser = document.createElement('a');
parser.href = 'http://heise.de/bar';
parser.hostname; // => 'heise.de'
pathname = parser.pathname; // => '/bar'
if (pathname[0] != '/')
pathname = '/' + pathname // Fix IE11
One advantag...
Icon font vertical alignment in Windows
I had an issue with icons from an icon font aligning differently on Linux, iOS and Windows (seemingly browser-independent). With vertical-align:middle
, they aligned properly on Linux, iOS and macOS, whereas with a vertical-align
of -18%
, it looked good on Windows and iOS, but not Linux.
Further investigation showed that not only icons, but also normal capital letters aligned differently. No setting of vertical-align
could fix this, neither top
, bottom
, middle
, nor additional paddings or margins. It seems like browsers take the...
Hiding the clear input button of Edge (with EdgeHTML engine)
Edge (and some versions of Internet Explorer, like IE11) use to render a × clear input button on text fields. While this is intended as a nicety for users, it comes in annoying when you've built and styled your own clear input button.
Hide the Edge × with this pseudo selector:
input::-ms-clear
display: none
Differences between transactions and locking
Web applications can be used by multiple users at the same time. A typical application server like Passenger has multiple worker processes for a single app. In a distributed deployment setup like we use at makandra you will even have multiple application servers, each with their own worker pool.
This means that your code needs to deal with concurrent data access. The two main tools we use to cope with concurrency are database transactions and distributed locks. These two are not interchangeable. You ca...
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...
How to debug issues with zeitwerk and Rails
In case you have trouble with the zeitwerk autoloader, you can check out the documentation Autoloading and Reloading Constants and Classic to Zeitwerk HOWTO for some debugging hints.
For myself it was useful to print the registered constants and the file references during the boot. Therefore you need to add Rails.autoloaders.log!
at the end of your config/application.rb
file. You could also run `bin...
Waiting for page loads and AJAX requests to finish with Capybara
If you're using the Capybara webdriver, steps sometimes fail because the browser hasn't finished loading the next page yet, or it still has a pending AJAX request. You'll often see workarounds like
When I wait for the page to load
Then ...
Workarounds like this do not work reliably, will result in flickering tests and should be avoided. There is no known reliable way to detect if the browser has finished loading the page.
Solution
Instead you should wait until you can observe the result of a page load. E.g. if y...
ActiveType 1.2 supports "change_association"
With ActiveType 1.2 you can modify associations (has_many
etc.) after they have been defined.
One common use case for this is to change an association inside a form model, like this:
class Credential < ActiveRecord::Base
end
class User < ActiveRecord::Base
has_many :credentials
end
class SignUpCredential < ActiveType::Record[Credential]
end
class SignUp < ActiveType::Record[User]
change_association :credentials, class_name: 'SignUpCredential'
end
Now, if you load `credentials...
CSS: Don't target multiple vendor-prefixed pseudo-elements in a single rule
Some pseudo-elements need to be addressed with vendor prefixes. E.g. ::selection
is not supported by Firefox, you need to use ::-moz-selection
instead.
What you cannot do is to define a single CSS rule to address both the standard and vendor-prefixed form:
::selection, ::-moz-selection {
background-color: red;
}
This rule will be ignored by all browsers. The reason is that if a browser doe...
Rails: namespacing models with table_name_prefix instead of table_name
When you want to group rails models of a logical context, namespaces are your friend. However, if you have a lot of classes in the same namespace it might be tedious to specify the table name for each class seperately:
class Accounting::Invoice < ApplicationRecord
self.table_name = 'accounting_invoices'
...
end
class Accounting::Payment < ApplicationRecord
self.table_name = 'accounting_payments'
...
end
A replacement for the self.table_name
-assignment is the table_name_prefix
in the module definition:
modu...
Project maintenance: four levels of code quality
Code quality can be measured in four levels:
- (Working code)
- Reliable code (minimum)
- Readable code (ok for short-lived code)
- Changeable code (standard level)
The code quality of a project directly impacts its maintainability.
Generally you should aim for level 3. If the code will stay for less than a few months, it may stay at level 2. Never go below level 1.
0. Working code
You have implemented that feature and it works. Congrats! You have reached level zero, which means three levels of code quality lie ahead.
First, m...
Rails: Remove Blank Values from Collections
tl;dr
Since Rails
6.1+
you can use.compact_blank
or.compact_blank!
to remove blank values from collections (e.g. arrays).
Remove nil
values from an array
['foo', nil].compact
# => ['foo']
# You can use the splat operator to ignore nil values when constructing an array
['foo', *nil]
# => ['foo']
Remove blank values from collections
Array
array = [1, "", nil, 2, " ", [], {}, false, true]
# Any Rails version
array.reject(&:blank?)
# => [1, 2, true]
# Since Rails 6.1+
array.compact_blank
# ...
Ruby constant lookup: The good, the bad and the ugly
In Ruby, classes and modules are called constants. This card explains how Ruby resolves the meaning of a constant.
The good
E. g. in the following example, Array
could mean either Foo::Array
or simply Array
:
class Foo
def list
Array.new
end
end
What Ruby does here is to see if the name Array
makes sense inside of Foo::
, and if that fails, resolves it to ::Array
(without a namespace).
The bad
This is relevant for old Ruby versions. Ruby 2.5+ removes top-level constant lookup whi...
CSS Support Guide for Email Clients
CSS support in major e-mail clients is horrible.
This will give you an overview what you will not be able to use across all clients.
See also
Postgresql: Paginate and count in one query using window functions
When paginating records, we usually need to know the number of total records in order to render pagination links. Popular pagination libraries like will_paginate or Kaminari do this for us by simply issuing an extra query, like this:
SELECT post.* FROM posts LIMIT 20 OFFSET 100;
SELECT COUNT(*) FROM posts;
This is fine most of the time. But rarely, you might have very complicated WHERE
conditions or a subquery that takes time to run. In thes...
JavaScript: Testing whether the browser is online or offline
You can use the code below to check whether the browser can make connections to the current site:
await isOnline() // resolves to true or false
The code
The isOnline()
function below checks if you can make real requests by re-fetching your site's favicon. If the favicon cannot be downloaded within 6 seconds, it considers your connection to be offline.
async function isOnline({ path, timeout } = {}) {
if (!navigator.onLine) return false
path ||= document.querySelect...