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
image-to-DataURI converter: Duri.me
Small web application where you can upload an image (PNG, JPEG, GIF) and generate a base64-encoded version of it.
You can copy the result as
- HTML
<img>
tag with data URI, - CSS rule with
background-image
and data URI, - plain Base64-encoded data URI string.
A non-weird replacement for grouped_collection_select
Rails comes with grouped_collection_select
that appears to be useful, but isn't.
As an alternative, consider the flat_grouped_collection_select
found below. It takes a third argument that extracts the group from each element in the collection:
= form.flat_grouped_collection_select :user_id, users, :department, :id, :full_name
Here is the monkey-patch:
class ActionView::Helpers::FormBuilder
def flat_grouped_collection_selec...
Rails 3 ActiveRecord::Persistence#becomes does not copy changed attributes
Note: ActiveRecord::Base#becomes
has a lot of quirks and inconsistent behavior. You probably want to use ActiveType.cast
instead.
This issue will be encountered when relying on attribute_was
methods of ActiveModel::Dirty
after casting a model which has defaults to a form model, for example.
In my case a record with an assignable_values legacy value beca...
Testing regular expressions visually
Developing complex regular expressions quickly blows my mind. Here are some online regex editors that help you by highlighting matching text and capture groups:
- Ruby:
- Javascript:
Reverse-proxying web applications with Apache 2.4+
Note: Making a reverse proxy with nginx is much more straightforward.
A reverse proxy is a "man in the middle" server that tunnels requests to another server. You can use for things like:
- Expose a local service that you cannot directly reach over the internet
- "Change" the domain or path of a web application by rewriting them on the fly
- Instantly change servers that respond to a name or ...
Manually trigger a delegated DOM event
When you register a delegated event using on
(or the deprecated delegate
/ live
), it is somewhat hard to manually trigger these events manually, e.g. for testing.
After trying jQuery's trigger
to no avail, I had success by using native Javascript methods to create and dispatch an event. For instance, to trigger a mousedown
event:
element = $('...').get(0);
event = new MouseEvent('mousedown', { view: window, cancelable: true, bubbles: true }...
Upgrading from Capistrano 2 to 3
Capistrano 3 is a major rework of the framework and requires several adjustments to your deploy configuration files. The biggest change is that they moved away from their custom DSL and use Rake
instead. For connecting with and operating on the servers, they bring a new gem SSHKit
which does the heavy lifting. It's SSHKit's DSL that is used anywhere inside the Rake tasks. See #Resources at the bottom for examples.
Step 1: Upgrade guide
For migration from 2 to 3, follow this tutorial: [Capistrano 3 Upgrade Guide](https://semaphorec...
Cucumber step to pick a datetime in Rails' horrible datetime_select
Please don't use the horrible datetime_select
helper. It has a terrible UI. Always prefer to use a visual time picker like Rome instead.
In case everything has failed and you do need a Cucumber step to pick a datetime datetime_select
, here it is:
When(/^I select the time (\d+)\-(\d+)\-(\d+) (\d+):(\d+) from "(.*?)"$/) do |year, month, day, hour, minute, label_text|
label = page.find('label', text: label_text)
id = label[...
Savon testing: How to expect any message
When using Savon to connect a SOAP API, you may want to use Savon::SpecHelper
to mock requests in your tests as described in their documentation.
When sending a message body, the savon
mock object requires a message to be set, like this:
savon.expects(:action_name).with(message: { user_id: 123 }).returns('<some xml>')
If you want to stub only the returned XML and do not care about request arguments, you can not omit with
as Savon's helper will complain:
savo...
Testing setTimeout and setInterval with Jasmine
Jasmine has a jasmine.clock()
helper that you can use to travel through time and trigger setTimeout
and setInterval
callbacks:
beforeEach(function() {
timerCallback = jasmine.createSpy("timerCallback");
jasmine.clock().install();
});
afterEach(function() {
jasmine.clock().uninstall();
});
it("causes a timeout to be called", function() {
setTimeout(function() {
timerCallback();
}, 100);
expect(timerCallba...
A solid and unobtrusive plugin for form field placeholders
jquery-placeholder
is a simple jQuery plugin that enables form placeholders in browsers that do not support them natively, i.e. IE < 10.
Properties
- Works in IE6.
- Automatically checks whether the browser natively supports the HTML5 placeholder attribute for input and textarea elements. If this is the case, the plugin won’t do anything. If @placeholder is only supported for input elements, the plugin will leave those alone and apply to textareas exclusively. (This is the case for Safari 4, Opera 11.00, and possibly other browsers.)
...
Make "rake notes" learn about Haml, Sass, CoffeeScript, and other file types
Rails comes with a Rake task notes
that shows code comments that start with "TODO", "FIXME", or "OPTIMIZE".
While it's generally not good practice to leave them in your code (your work is not done until it's done), in larger projects you will occasionally have to use them as other parts of the application that you depend upon are not yet available.
To keep track of them, run rake notes
. Its output looks something like this:
$ rake notes
app/controllers/fron...
Using form models (aka decorators) with Devise
To use a form model with devise, you can simply override #resource_class
in a controller. A typical use case would be the registrations controller, as users will need some fields only on sign-up. Example:
class Frontend::Authentication::RegistrationsController < Devise::RegistrationsController
private
def resource_class
FrontendUser::AsSignUp # my decorator class, extending from FrontendUser
end
end
Fontawesome 4 helper classes
Fontawesome 4 ships with many useful CSS helper classes.
Enlarge Icon
Add fa-lg
(133%), fa-2x
, fa-3x
, fa-4x
or fa-5x
.
Fixed-width Icon
Add fa-fw
. Will give all icons the same width.
Styling Lists
Add fa-ul
to a <UL>
and fa fa-<icon name> fa-li
to a <LI>
to give the list items custom "bullets".
Bordered Icon
Add fa-border
to get a border around the icon.
Spinning Icon
Add fa-spin
to make any icon rotate. Suggested icons: fa-spinner
, fa-refresh
, fa-cog
. Doesn't work in IE <10.
Ro...
Rails 4 introduced collection_check_boxes
Starting from Rails 4.0, you can use a special form options helper called #collection_check_boxes
. It behaves similar to #collection_select
, but instead of a single select field it renders a checkbox and a label for each item in the collection.
= form_for @post do |form|
= form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial
How generated form params look like
---------------------------------...
Thread-safe collections in Ruby
When using threads, you must make your code thread-safe. This can be done by either locking (mutexes) all data shared between threads, or by only using immutable data structures. Ruby core classes like String
or Array
are not immutable.
There are several gems providing thread-safe collection classes in Ruby.
concurrent-ruby
The concurrent-ruby gem provides thread-safe versions of Array
and Hash
:
sa = Concurrent::Array.new # supports standard Array.new forms
sh = Co...
Add an alternative image source for broken images
Awesome hack by Tim VanFosson:
<img src="some.jpg" onerror="this.src='alternative.jpg'" />
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...
Verifying doubles in RSpec 3
RSpec 3 has verifying doubles. This breed of mock objects check that any methods being stubbed are present on an instance of a given class. They also check methods aren't called with the wrong number of arguments.
This dual approach allows you to move very quickly and test components in isolation, while
giving you confidence that your doubles are not a complete fiction.
You should always prefer using a verifying double to using an old-school mock
...
Communication between collaborating directives in Angular
What if a complicated component comes along that is naturally modeled by multiple directives? This group of directives, as a whole, form a single self contained component. None of directives in the group can stand alone because they only make sense when used together; they collaborate; they are aware of each other and need to communicate with each other.
This post will discuss best practices for managing communication among collaborating directives and illustrate these practices with an example.
How to enable WebGL in Chrome
Check your GPU state on chrome://gpu. If it reads "WebGL: Hardware accelerated" in the first list, you're set. Else:
- Make sure chrome://flags/#disable-webgl is disabled (there should be a link "Enable")
- If that does not help, try to additionally enable chrome://flags/#ignore-gpu-blacklist.
Exporting to Excel from Rails without a gem
See this Railscast.
Basically you can simply write views like index.xlsx.erb
:
<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<Worksheet ss:Name="Sheet1">
<Table>
<Row>
<Cell><Data ss:Type="String">ID</Data></Ce...
Be careful when using buttons without a "type" attribute
Be careful when using buttons without a type
attribute, since browsers will consider them the default submit button of a form.
Suppose you have this form:
<form action="/save">
<input type="text" />
<button onclick="alert('Alert!')">Alert</button>
<button type="submit">Save</button>
</form>
If you press the enter key inside in the text input, browsers will trigger the first button and show the alert.
To fix this, add a type="button"
attribute to the first button.