ActionMailer: Previewing mails directly in your email client

In Rails, we usually have a mailer setup like this:

class MyMailer < ActionMailer::Base

  def newsletter
    mail to: 'receiver@host.tld',
      from: 'sender@host.tld',
      subject: 'My mail'
  end

end

If you want to preview your mail in the browser, you can use the Action Mailer Preview. To inspect the mail directly in your email client, just create an .eml file and open it with your client:

mail = MyMailer.newsletter
Fil...

HTML emails with inline stylesheets and webpacker

Many mail clients do not support external style sheets. Some even require all styling inline, which means you'll have to do your styling inline. For Rails applications, you can use Roadie or premailer, which lets you keep your well-structured CSS files and do the inlining for you.

See Designing HTML email

Since Roadie is now in passive maintenance mode, we go with premailer:

Include premailer in your Gemfile:

gem 'premailer-ra...

CSS: Flex and "min-width"

min-width is known as a CSS property that can be set to define a least width for an element. Surprisingly, it can also be used to set something that feels like max-width.

min-width in a flex context

While the default min-width value is 0 (zero), for flex items it is more like "auto". This can make block elements take up much more space than desired, even stretching their container beyond the screen edge on small screens.

![Image](/makandra/66994/attach...

Using local fonts with Webpack / Webpacker

When we want to use our own (or bought) fonts in an application with Webpack(er), we have two options. We can

  • put the fonts directly into your Webpack's assets folder or
  • write an npm package with an own sass file that can be imported from the Webpack manifest.

Load fonts from your assets folder

The first option turns out to be straightforward: Import the stylesheets in the index.js of the pack you're using:

// webpack_source_path/application/index.js

import './stylesheets/reset'
import...

Rails: Passing array values to tag helpers like link_to

From at least Rails 4, the ActionView tag helper turns Array values of HTML options into a single space-separated string.
This means you can pass an array to :class options:

extra_classes = %w[one two]

= link_to 'Dashboard', root_path, class: ['btn', 'btn-primary', *extra_classes]
=> <a href="/" class="btn btn-primary one two">Dashboad</a>

= content_tag 'div', 'Hello World', class: %w[alert alert-info]
=> <div class="alert alert-info">Hello World</div>...

Upgrade guide for moving a Rails app from Webpack 3 to Webpack 4

Webpacker is Rails' way of integrating Webpack, and version 4 has been released just a few days ago, allowing us to use Webpack 4.

I successfully upgraded an existing real-world Webpack 3 application. Below are notes on everything that I encountered.
Note that we prefer not using the Rails asset pipeline at all and serving all assets through Webpack for the sake of consistency.

Preparations

  • Remove version locks in Gemfile for webpacker
  • Remove version locks in package.json for webpack and webpack-dev-server
  • Install by ca...

Carrierwave: Built-in resize methods

Carrierwave includes some handy helper methods you can use to resize your images. Here is a quick summary of them, if you need more details read the docs. You can also use all command line options from RMagick directly if these helpers are not good enough for you.

resize_to_limit(width, height)
resize_to_fit(width, height)
resize_to_fi...

JavaScript without jQuery

This is a presentation from 2019-01-21.

Summary

  • We want to move away from jQuery in future projects
  • Motivations are performance, bundle size and general trends for the web platform.
  • The native DOM API is much nicer than it used to be, and we can polyfill the missing pieces
  • Unpoly 0.60.0 works with or without jQuery

Is jQuery slow?

From: Sven
To: unpoly@googlegroups.com
Subject: performance on smartphones and tablets

Hello

I just used your framework in one project and must say,
I am really pleased with it -- but o...

How not to turn your application into a spam relay

Spammers have started abusing other application to send their spam. This works like this:

  • The application has some form that allows to send e-mails to arbitrary users. This can be something like a newsletter sign-up with a double-opt in, a registration confirmation e-mail (or even password reset e-mail), or something similar.
  • The e-mail also includes some reflected text. For example, a user may be able to give their name, and the name is used within the e-mail. The spammer will then abuse that text to include his advertisment.

Potentia...

Auto-generating plain-text bodies for HTML e-mails in Rails apps

When building an application that sends e-mails to users, you want to avoid those e-mails from being classified as spam. Most obvious scoring issues will not be relevant to you because you are not a spammer.

However, your application must do one thing by itself: When sending HTML e-mails, you should include a plain-text body or tools like SpamAssassin will apply a significant score penalty. Here is how to do that automatically.

  1. Add premailer-rails to your Gemfile and bundle.
  2. Done! ...

Upgrading Ruby from 1.8.7 to 2.3.5

Suggested Workflow

Set the ruby version in .ruby-version to 2.3.5, then perform these steps one by one, fixing errors as they occur:

  1. Update gems as listed below, and bundle
  2. Boot a Rails console - see below for a list of changes you will probably need
  3. Run Specs with --backtrace option
  4. Run Cucumber features (with Geordi's --debug option)
  5. When all tests are green, look through your Gemfile and remove as many version constraints as possible.
  6. Boot the application in different environements to spot further issues, e...

Ruby: Reading and writing CSVs

In ruby you can easily read and write CSVs with the standard CSV library class.

On top of this, you can use the gem smarter_csv for reading (not writing) CSVs in a more comfortable way:

  • Keep in mind, that the development of this gem is in an unknown state and the 2.0 release seems to happen never
  • The API will change completely for 2.0, so you might find a bunch of unrelated documentation for 1.2

Here is an example...

How to: Use Ace editor in a Webpack project

The Ace editor is a great enhancement when you want users to supply some kind of code (HTML, JavaScript, Ruby, etc).
It offers syntax highlighting and some neat features like auto-indenting.

For Webpack 3+

Integrate as described in the documentation. For example load ace Editor like this:

  function loadAceEditor() {
    return import(/* webpackChunkName: "ace" */ 'ace-builds/src-noconflict/ace').then(() => {
      return import(/* webpackChunkName: "ace" */ 'ace-builds/webpack-r...

Rubymine FileType mismatch

If your Rubymine does not recognize a file type correctly although you have entered the unmistakeable file extension like material_orders_controller.rb, this may help you:

Causing the Problem

Sometimes you create a new file and forget to enter the ending like material_orders_controller
Rubymine handles such files per default as simple txt files.
You delete this file and create a new one with correct ending: material_orders_controller.rb. But still Rubymine treats this file as text file, no highlighting is available.

What happene...

How to: expand an element's cover area beyond its container

Occasionally, your designer will hand you designs where elements break the layout's horizontal container width, like navigation buttons of a slider that should be at the left/right of the browser window, or simply by applying a background color that reaches until the left and right of the browser window.

In the past, we've done some horrible things to achieve that. Like margin: 0 -10000px plus overflow-x: hidden.
There is a much saner approach.

Consider the following markup:

<body>
  <div class="container">
    <div class="sec...

Katapult 0.5.0 released

New Features

  • Deployment ready for Opscomplete
  • Copying view and controller templates over to target application during
    basics configuration or via new command katapult templates.
  • "Usage" section in README rewritten: Now describes two usage scenarios.

Improvements

  • Generating a fixed Gemfile.lock. Run bundle update after code generation to
    update all gems to recent versions.
  • Better deployment with Webpack
  • Navigation only rendered if requested
  • Some minor fixes

jQuery: How to remove classes from elements using a regular expression

jQuery's removeClass removes the given class string from an element collection. If you want to remove multiple/unknown classes matching a given pattern, you can do that.

For example, consider a DOM node for the following HTML. We'll reference it by $element below.

<div class="example is-amazing is-wonderful"></div>

Option A: Selecting classes, then removing them

You can iterate over existing classes, and select matching ones. The example below is ES6, on ES5 could write something similar using jQuery.grep.

let classes ...

Accessing Rails config in webpack(er)

It is possible to access Rails config (for example secrets) from within your webpack bundles, thanks to rails-erb-loader. When using webpacker, the setup is like this:

  1. Install rails-erb-loader:

    yarn add rails-erb-loader
    
  2. Add this to your config/webpacker/environment.js:

    environment.loaders.prepend('erb', {
      test: /\.erb$/,
      enforce: 'pre',
      use: [{
        loader: 'rails-erb-loader',
      }]
    })
    
  3. Start using erb. For examp...

Does <html> or <body> scroll the page?

TL;DR: All modern browsers default to using the <html> element as the main document viewport. In CSS, prefer to set overflow properties to html (or :root).

Scrolling the main viewport with JavaScript

The browser's main document viewport is also scrollable by default. The element that corresponds to the main viewport is either <html> (document.documentElement) or <body> (document.body). Which one depends on the browser.

When you want to update the current `sc...

Raising JavaScript errors in Ruby E2E tests (RSpec, Cucumber)

A JavaScript error in an E2E test with Selenium will not cause your test to fail. This may cause you to miss errors in your frontend code.

Using the BrowserConsole helper below you can check your browser's error console from your E2E tests.

The following will raise BrowserConsole::ErrorsPresent if there is an error on the browser console:

BrowserConsole.assert_no_errors!

Ignoring errors

You can ignore errors by their exact message:

BrowserConsole.ignore('Browser is burning')

You can ignore errors with me...

HTML file inputs support picking directories

HTML's <input type="file"> accepts a single file. You can allow multiple files via <input type="file" multiple>.
But sometimes, selecting multiple files is not enough and can be cumbersome for the user. Enter webkitdirectory:

<input type="file" webkitdirectory multiple>

Using webkitdirectory switches the browser's file picker to select a directory. All files inside that directory, and inside any nested subdirectories, will be selected for the file input.

This can be useful when users want to upload all files from a nested dire...

Rails < 5: How to get after_commit callbacks fired in tests

If you use transactional_fixtures or the database_cleaner gem with strategy :transaction, after_commit callbacks will not be fired in your tests.

Rails 5+

Rails 5 has a fix for this issue and no further action is needed.

Rails 3, Rails 4

Add the gem test_after_commit to your test group in the Gemfile and you are done. You don't need to change the database strategy to deletion (wh...

Do not use "flex: 1" or "flex-basis: 0" inside "flex-direction: column" when you need to support IE11

Flexbox is awesome. Most of it even works in IE11, but flex: 1 won't work reliably in Internet Explorer.
This it because implicitly sets flex-basis: 0 which IE fails to support properly.

Example

Consider the following HTML and CSS.

<div class="container">
  <div class="child">
    foo
  </div>
  <div class="bar">
    bar
  </div>
</div>
.container {
  display: flex;
  flex-direction: column;
}

.child {
  flex: 1;
}

See it in action at Plunker.

Background

...

HTML forms with multiple submit buttons

Most forms have a single submit button that will save the record when pressed.

Sometimes a form needs additional submit buttons like "accept" or "reject". Such buttons usually attempt a state transition while updating the record.

To process a form with multiple buttons, your server-side code will need to know which button was pressed. To do so you can give each submit button a different [formaction] attribute. This will override the ...