Rails: Including HTML in your i18n locales

TL;DR

Append your locale keys with _html to have them marked as html_safe and translate them with = t('.text_html').

When you're localizing a Rails application, sometimes there is this urge to include a little HTML. Be it some localized link, or a set of <em> tags, you'd like to have it included in the locale file. Example:

# Locale file
en:
  page:
    text: 'Please visit our <a href="https://www.corporate.com/en">corporate website</a> to learn more about <em>the corporation</em>.'
    
# HAML
= t('.text')
    
# D...

Capistrano task to tail remote application logs of multiple servers

When your application is running on a multi-server setup, application logs are stored per server (unless you choose a centralized logging solution).
Here is a Capistrano task that connects to all servers and prints logs to your terminal like this:

$ cap production app:logs
00:00 app:logs
      01 tail -n0 -F /var/www/your-application/shared/log/production.log | while read line; do echo "$(hostname): $line"; done
      01 app01-prod: Started GET "/sign_in" for 1.2.3.4 at 2018-04-26 11:28:19 +0200
      01 app01-prod: Proc...

Unpoly: Loading large libraries on-demand

When your JavaScript bundle is so massive that you cannot load it all up front, I would recommend to load large libraries from the compilers that need it.

Compilers are also a good place to track whether the library has been loaded before. Note that including same <script> tag more than once will cause the browser to fetch and execute the script more than once. This can lead to memory leaks or cause duplicate event handlers being registered.

In our work we mostly load all JavaScript up front, since our bundles are small enough. We recent...

jQuery: How to replace DOM nodes with their contents

You know that you can use jQuery's text() to get an element's contents without any tags.
If you want to remove only some tags, but keep others, use contents() and unwrap(). Here is how.

Consider the following example element.

$container = $('<div><strong>Hello</strong> <em>World</em></div>')

Let's say we want to discard any <em> tags, but keep their contents.
Simply find them, then dive into their child nodes via contents, and use unwrap replace their ...

When you want to format only line breaks, you probably do not want `simple_format`

For outputting a given String in HTML, you mostly want to replace line breaks with <br> or <p> tags.
You can use simple_format, but it has side effects like keeping some HTML.

If you only care about line breaks, you might be better off using a small, specialized helper method:

def format_linebreaks(text)
  safe_text = h(text)
  paragraphs = split_paragraphs(safe_text).map(&:html_safe)

  html = ''.html_safe
  paragraphs.each do |paragraph|
    html << content_tag(:p, paragraph)
  end
  html
end

Full di...

Rails: How to provide a public link in a mail

Lets say we have a user with a contract whereas contract is a mounted carrierwave file.

Now we want to send the link to the contract in a mail. For this use case join the root_url with the public contract path in the mailer view:

Plain text email

URI.join(root_url, @user.contract.url)

HTML email

link_to('Show contract', URI.join(root_url, @user.contract.url).to_s)

Note: You need to follow [http://guides.rubyonrails.org/action_mailer_basics.html#g...

Fixing: Gem::Package::PathError: installing into parent path is not allowed

This might be a known issue with Rubygems 2.5.1. This will help:

gem update --system

Generating test images on the fly via JavaScript or Ruby

When you need test images, instead of using services like lorempixel or placehold.it you may generate test images yourself.

Here we build a simple SVG image and wrap it into a data: URI. All browsers support SVG, and you can easily adjust it yourself.
Simply set it as an image's src attribute.

JavaScript

Simple solution in modern JavaScript, e.g. for use in the client's browser:

function svgUri(text) {
  let svg = `
    <svg wid...

How to resize your boot partition when there is an encrypted partition after it

Boot partitions from installations prior to the 16.04 era are terribly small. When you install updates and encounter errors due to a full /boot partition, consider risizing it.

If you can't do the steps described below, ask someone experienced to help you out.
This has worked 100% so far. 1 out of 1 tries. ;)

Scenario A: There is unassigned space on your physical drive

When there is some unpartitioned space on your drive, increasing the size of /boot is actually very easy (even though the list below is rather long). It only takes a...

Geordi 1.9 released

New features:

geordi delete_dumps [directory]

Recursively search for files ending in *.dump and offer to delete those. When no argument is given, two default directories are searched for dump files: the current working directory and ~/dumps (for dumps created with geordi).

geordi drop_databases

Delete local MySQL/MariaDB and Postgres databases that are not whitelisted.

Authentication is handled via PAM for Postgres and MariaDB, via .my.cnf with fallback to mysql -p for MySQL. Different connection methods can be chosen via ...

Rails: Overriding view templates under certain conditions only

Rails offers a way to prepend (or append) view paths for the current request. This way, you can make the application use different view templates for just that request.

Example

A use case of this is a different set of view templates that should be used under certain circumstances:

class UsersController < ApplicationController

  before_action :prepare_views
  
  def index
    # ...
  end    
  
  private
  
  def prepare_views
    if <condition>
      prepend_view_path Rails.root.join('app', 'views', 'special')
    end
  end
 ...

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...

HTML5: disabled vs. readonly form fields

Form fields can be rendered as noneditable by setting the disabled or the readonly attribute. Be aware of the differences:

disabled fields

  • don’t post to the server
  • don’t get focus
  • are skipped while tab navigation
  • available for button, fieldset, input, select, textarea, command, keygen, optgroup, option

Browser specific behavior:

  • IE 11: text inputs that are descendants of a disabled fieldset appear disabled but the user can still interact with them
  • Firefox: selecting text in a disabled text field is no...

How to: Restart vnc server for geordi

Trying to open a vnc window with geordi geordi vnc ended up with this error:

> VNC viewer could not be opened:
vncviewer: ConnectToTcpAddr: connect: Connection refused

Check if vncserver 17 (default geordi session) is running:

ps -aux|grep vnc

If you see Xvnc4 :17 then the server is already running. Kill this server if it is already running.

vncserver -kill :17

Als...

Mysql::Error: BLOB/TEXT column can't have a default value

mysql> SELECT @@global.version;
+------------------+
| @@global.version |
+------------------+
| 5.6.30           |
+------------------+
1 row in set (0,00 sec)

MySQL 5.6 Reference Manual says "BLOB and TEXT columns cannot have DEFAULT values".

If you want to run migrations in development here are two variants which might help. If you are not sure about the side effects (e.g. your application is broken when it doesn't set additional default values on application side, too...

Chrome: Making high-resolution website screenshots without add-ons

If you want to make a screenshot of a website that works well in print or on a high-DPI screen (like Apple Retina displays), here is how you can capture a high-resolution screenshot.

You can do this without an addon:

  • Open the website
  • If you have multiple monitoros:
    • Resize the Chrome window so it covers multiple monitors (in Linux you can hold ALT and resize by dragging with the right mouse button)
    • Zoom into the page using CTRL + and CTRL - so it covers most of the window area. Leave a little padding on the left and right so...

XHR is not JSON

When a Rails controller action should handle both HTML and JSON responses, do not use request.xhr? to decide that. Use respond_to.

I've too often seen code like this:

def show
  # ...
  if request.xhr?
    render json: @user.as_json
  else
     # renders default HTML view
  end
end

This is just plain wrong. Web browsers often fetch JSON via XHR, but they (should) also send the correct Accept HTTP header to tell the server the data they expect to receive.

If you say request.xhr? as a means for "wants JSON" you are ...

About-Payments: Platform to compare payment providers

About-Payments is here to help you to accept payments online and
find the best payment service provider for your e-commerce business.

Carrierwave: Deleting files outside of forms

TL;DR Use user.update!(remove_avatar: true) to delete attachments outside of forms. This will have the same behavior as if you were in a form.


As you know, Carrierwave file attachments work by mounting an Uploader class to an attribute of the model. Though the database field holds the file name as string, calling the attribute will always return the uploader, no matter if a file is attached or not. (Side note: use #present? on the uploader to check if the file exists.)

class User < ApplicationRecord
  mount :avatar, ...

Form letters with LibreOffice Writer

This is painful. Consider using Microsoft Office or switching careers. If you need to write < 20 letters consider doing it manually.

So you didn't listen and here it comes:

  1. Ignore the Mail Merge Wizard. It will crash or destroy your document.
  2. Export your addresses, recipient names, etc. as a .ods spreadsheet (.xls, .xlsx, .ods). Use any columns that work for you, but be consistent. I like to use one column for the address, one column for the salutation line.
  3. Import the spreadsheet as an address book source: *Tools => Add...

How to use cookies with curl

When making requests using curl, no cookies are sent or stored by default.
However, you can tell curl to re-use cookies received earlier (or forge your own cookies).

There are 2 command line switches you need to use:

  • -c will write cookies to a given file
  • -b will read cookies from a given file

Example

The remote server sets a "foo" cookie to value "bar". We tell curl to store them to a file at /tmp/cookies using the -c switch.

$ curl -c /tmp/cookies http://httpbin.org/cookies/set?foo=bar

You may look at the file, ...

Rails: Migration helper for inserting records without using models

You should avoid using application models in your migrations. But how else could you create records in a migration?

The most basic way is to write plain SQL, but since INSERT statements are no pleasant write for Rubyists, here is a simple wrapper:

Record creation helper for migrations

The helper method below takes a table name and a hash of attributes, which it inserts into the specified table. Copy it over to your migration and profit!

  private

  def insert_record(table, **attributes)
    attributes.merge!...

How to fix HTML elements being cut off when printing

When you print (or print preview) and elements are cut off (e.g. after 1st page, or "randomly") you should check your CSS rules for these:

  • Is there an element with "display: inline-block" that surrounds your content? Make sure it has "display: block" for printing.
    This primarily affects Firefox and Internet Explorer. Chrome seems to be able to handle inline-block elements in most cases.

  • Does the element itself, or a container, define "overflow: hidden"? Use "overflow: auto" (or maybe "overflow: visible") instead.

  • Is th...

HTML: Making browsers wrap long words

By default, browsers will not wrap text at syllable boundaries. Text is wrapped at word boundaries only.

This card explains some options to make browsers wrap inside a long word like "Donaudampfschifffahrt".

Option 1: hyphens CSS property (preferred)

Modern browsers can hyphenate natively. Use the hyphens CSS property:

hyphens: auto

There is also hyphens: none (disable hyphenations even at &shy; entities) and hyphens: manual (hy...