Showing a custom maintenance page while deploying
Note
The maintenance mode is enabled on all application server as soon as the file
/public/system/maintenance.html
is present.
Installation
Add this line to your application's Gemfile:
gem 'capistrano', '~> 3.0'
gem 'capistrano-maintenance', '~> 1.0'
Add this line to you application's Capfile:
require 'capistrano/maintenance'
Enable task
Present a maintenance page to visitors. Disables your application's web interface by writing a #{maintenance_basename}.html
file to each web server. The servers m...
Puppet: Delete certificate request
To delete a certificate request run sudo puppet ca destroy $your.full.hostname
on your puppetmaster.
How to open a new tab with Selenium
Until recently, you could open a new tab via window.open
when using execute_script
in Selenium tests. It no longer works in Chrome (will show a "popup blocked" notification).
This is because browsers usually block window.open
unless the user interacted with an element for security reasons. I am not sure why it did work via Selenium before.
Here is an approach that will insert a link into the page, and have Selenium click it:
path = "/your/path/here"
id = "helper_#{SecureRandom.hex(8)}"
execute_script <<-JAVASCRIPT
...
How to encode or decode quoted-printable strings
E-mails are usually encoded using Quoted Printable. Here is how to decode or encode such strings.
You probably know Quoted Printable from e-mail bodies appearing in Rails logs, where =
s become =3D
s in URLs, or where long lines are split up and trailed by =
after each split.
Decode Quoted Printable
Decoding such strings is actually quite simple using plain Ruby:
"foo=3Dbar".unpack('M')[0]
# => "foo=bar"
Note that unpack
will return an array. Our result is the 1st item.
...
A collection of SVG Logos for developers
A collection of 700+ svg vector logos. The logos are optimized (removed duplicated paths / excessive groups / empty defs, linting, etc).
Almost 100 logos were recreated from rastered images #vectorized.
All logos appearing on the site are the property of their respective owners.
RSpec & Devise: How to sign in users in request specs
You know that Devise offers RSpec test helpers for controller specs. However, in request specs, they will not work.
Here is a solution for request specs, adapted from the Devise wiki. We will simply use Warden's test helpers -- you probably already load them for your Cucumber tests.
First, we define sign_in
and sign_out
methods. These will behave just like ...
Adjust cron jobs to allow full backtraces for rake tasks
As we get an exception notification, when a cron job fails, we wish to have the full backtrace in this mail. A rake task doesn't output the full backtrace by default, so you need the --backtrace
option.
Trigger
You will find fail mails with a shortened backtrace
#[...]
Tasks: TOP => some_namespace:some_task
(See full trace by running task with --trace)
What rake wants from you
Running the rake task like rake some_namespace:some_task --backtrace
How this works with whenever
Define a own job_type and use it for r...
Exclusive cronjobs with flock and whenever
I had a very frequent cronjob that in rare cases could be relatively slow. To avoid multiple instances of this cronjob running in parallel, I decided to use flock
to ensure that only one instance could run at a time.
flock
works by acquiring a lock to a file, and if it can do so running a command. In order not to wait but simply give up when the file is locked, you can add -n
:
flock /tmp/my.task.lock -n -c "bin/my-long-running-job"
Using whenever, and since this was a rake task, the follo...
Case Study: Analyzing Web Font Performance
Table of contents of the linked article:
What are Web Fonts?
- Advantages of Web Fonts
- Disadvantages of Web Fonts
- Fallback Fonts
- CSS3 @font Declaration Example
- Fallback Font Example
- Render Blocking and Critical Rendering Path
- FOIT
Optimizing Web Font Delivery Further
- Prioritize Based On Browser Support
- Choose Only Styles You Need
- Character Sets
- Host Fonts Locally or Prefetch
- Store in LocalStorage with Base64 Encoding
- Another Method
Web Font Pe...
How to deal with "invalid %-encoding" error in application for malformed uri
Lead by a discussion of this issue, I built in a middleware which answers those requests with [400] bad request
rather than raising an ArgumentError
.
I put it into app/util
and configured application.rb
like that:
# catches 'invalid %-encoding' error
require "#{Rails.root}/app/util/exception_app"
config.middleware.insert_before Rack::Runtime, ExceptionApp::Middleware
Note: Rails 4.2+ raises an ActionController::BadRequest
error instead of an ArgumentError
.
Reverse-proxying web applications with nginx
While you can use Apache as a reverse proxy, it tries to be too smart. Try nginx instead, it's much simpler to set up.
After struggling with Apache for quite a while, since I simply could not make it pass through the Digest Authentication of my target host (that I proxied to), I switched to nginx. Here is what I did.
-
Have nginx
sudo apt-get install nginx
-
Define your nginx config, e.g. at
/etc/nginx/conf.d/reverse-proxy.conf
:server { listen 127.0.0.1; location /...
AngularJS: How to force Content-Type on GET and DELETE requests
While you usually do not need a Content-Type
on GET request (which have a blank body), an external API may still force you to send one.
Angular's $http
service will strip that header when the request data (body) is blank. [1] This is possibly a misconception of RFC2616.
Here is how to send GET requests with a Content-Type
header in Angular.
Example
Consider this request:
$http({ me...
Web Fonts Performance // Speaker Deck
Web fonts are great. They are also be really bad for front-end performance because they block rendering. You may have experienced this on a slow cellular network. Staring at a blank page is no fun, especially when the content has already loaded.
This talk explores why browser have placed fonts on the critical path, and how we can work around this while still delivering a good user experience. It also takes a look at what the future will bring to web font performance: preloading hints, the font-display property, and HTTP/2.
Keeping web applications fast
Our applications not only need to be functional, they need to be fast.
But, to quote Donald Knuth,
premature optimization is the root of all evil (or at least most of it) in programming
The reasoning is that you should not waste your time optimizing code where it does not even matter. However, I believe there are some kinds of optimizations you should do right away, because
- they are either obvious and easy
- or they are very hard to do optimize later
This is an attempt to list some of those things:
On the server
...
Enumerators in Ruby
Starting with Ruby 1.9, most #each
methods can be called without a block, and will return an enumerator. This is what allows you to do things like
['foo', 'bar', 'baz'].each.with_index.collect { |name, index| name * index }
# -> ["", "bar", "bazbaz"]
If you write your own each
method, it is useful to follow the same practice, i.e. write a method that
- calls a given block for all entries
- returns an enumerator, if no block is given
How to write a canonical each
method
To write a m...
Rarely say yes to feature requests
A fantastic guide for a dilemma facing any web-based product.
Here’s a simple set of Yes/No questions that you can quickly answer before you add another item to your product roadmap.
Saying yes to a feature request – whether it’s a to an existing customer, a product enquiry, a teammate, or a manager – is immediately rewarding. It’s an unspoken transaction where you barter long term product focus in exchange for short term satisfaction. Buying short term joy for the cost of long term pain is the human condition.
- Does it fit your ...
Escape a string for transportation in a URL
To safely transport an arbitrary string within a URL, you need to percent-encode characters that have a particular meaning in URLs, like &
or =
.
If you are using Rails URL helpers like movies_path(:query => ARBITRARY_STRING_HERE)
, Rails will take care of the encoding for you. If you are building URLs manually, you need to follow this guide.
Ruby
In Ruby, use CGI.escape
:
# ✅ good
CGI.escape('foo=foo&bar=bar')
=> "foo%3Dfoo%26bar%3Dbar"
Do not ever use `URI.en...
Improving browser rendering performance
As the web is being used for more and more tasks, expectations rise. Not only should web pages offer rich interaction, they must be responsive in both size and interaction.
This imposes a paradoxon that needs to be solved by building performing applications. It's not enough any more to have your web site do crazy stuff, it is also required to do it crazy fast. This card is intended to give you an introduction to this emerging aspect of web development.
Read this introductory [performance study on Pinterest](http://www.smashingmagazine.com/...
httpclient: A Ruby HTTP client for serious business
While debugging an intricate issue with failed HTTP requests I have come to appreciate the more advanced features of the httpclient Rubygem.
The gem is much more than a lightweight wrapper around Ruby's net/http
. In particular:
- A single
HTTPClient
instance can re-use persistent connections across threads in a thread-safe way. - Has a custom and configurable SSL certificate store (which you probably want to disable by default...
Installing Node.js / npm under Ubuntu with nvm (with yarn)
I recommend install Node.js using nvm. This way you can have multiple Node versions in your ~/.nvm
. You also won't need to install global packages with sudo
anymore.
Node via nvm will automatically bring npm. yarn will automatically be available if corepack is enabled for node.
Installing nvm
DigitalOcean has a HOWTO for installing nvm on Ubuntu (16.04, [18.04](https://www.digitalocean.com/community/tutorials/how-to-...
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 ...
include_tags with the asset pipeline
You can include files from app/assets
or from the public
folder with javascript_include_tag
. The subtle difference that tells rails how to build the path correctly is a single slash at the beginning of the path:
<%= javascript_include_tag('ckeditor/config') %> # for assets/ckeditor/config.js
<%= javascript_include_tag('/ckeditor/ckeditor') %> # for public/ckeditor/ckeditor.js
This also applies to stylesheet_link_tag
.
Note that when you refer to a Javascript or stylesheet in /assets
you need to add it to [the list of asse...
How to split config/routes.rb in Rails 4
A word of caution
There should rarely be a reason for you to split up config/routes.rb
. If you need to, probably your whole application should be split up.
Split it anyway
Rails::Engine
looks at config.paths['config/routes.rb']
and registers its value with app.routes_reloader
. This means you could put routing files anywhere and then require them. However, I recommend to put any routing files into config/routes/
:
# config/routes/example.rb
Rails.application.routes.draw do
resources :example
end
After creating y...
Using tig
tig
is a command line explorer for Git that is just awesome. Install via apt-get
or brew
.
Handy commands
-
t
("tree"): Directory-structure based access. You'll see the current directory annotated with the latest change date and its author. Navigate with arrow keys or vim. -
b
("blame"): Opens the file under the cursor and annotates each line with change date and author. -
d
("diff"): LikeENTER
on a commit, but arrow keys will scroll the diff! -
/
: Search current view (e.g. commit list, diff). Jump to next hit withn
....