Howto prompt before accidentally discarding unsaved changes with JavaScript

Ask before leaving an unsaved CKEditor

Vanilla JavaScript way, but removes any other onbeforeunload handlers:

  $(function(){
    document.body.onbeforeunload = function() {
      for(editorName in CKEDITOR.instances) {
        if (CKEDITOR.instances[editorName].checkDirty()) {
          return "Unsaved changes present!"
        }
      }
    }
  }

A robuster implementation example

Note: Don't forget to mark the 'search as you type' forms with the skip_pending_changes_warning class.

var WarnBeforeAccidentallyDiscard...

Checking the character length of a text containing markup (e.g. WSYIWYG)

If you have a text that is edited by WSYIWYG-Editor but want some length checking nevertheless, you need to strip all tags and then the special characters:

  def hard_sanitize(text)
    ActionController::Base.helpers.strip_tags(text).gsub(/[^[:word:]]+/, " ")
  end
   :001 > hard_sanitize("This is <strong>beautiful</strong> <h1>markup<h1>")
   => "This is beautiful markup" 

If you allready have nokogiri on board, you can use that as well, though it has no extra benefit:

   :001 > Nokogiri::HTML("This is <strong>beau...

Resolving Element cannot be scrolled into view (Selenium::WebDriver::Error::MoveTargetOutOfBoundsError) on Mavericks

After I upgraded to Mac OS X Mavericks, I regularly got this error message when running Cucumber features with Selenium:

Element cannot be scrolled into view:[object XrayWrapper [object HTMLInputElement]] (Selenium::WebDriver::Error::MoveTargetOutOfBoundsError)

I had the Terminal window running the test on my secondary screen, whereas the Selenium-webdriven Firefox always started on my primary one. Now if I had focused the secondary screen when running the tests, Selenium could not start Firefox and switch to it (probably because t...

Ruby number formatting: only show decimals if there are any

Warning: Because of (unclear) rounding issues and missing decimal places (see examples below),
do NOT use this when dealing with money. Use our amount helper instead.


In Ruby, you can easily format strings using % (short for Kernel#sprintf):

'%.2f' % 1.23456 #=> 1.23
'%.2f' % 2 #=> 2.00

However, what if you only want the decimals to be shown if they matter? There is g! It will limit the total number of displayed digits, disregarding...

orgsync/active_interaction

Alternative approach to form models.

Workflows of Refactoring

Great slide deck about various forms of refactorings.

Rails always tries to use a layout with the same name as your controller

If you have a FooController and also have a layout app/views/layouts/foo.html, Rails will use this without being told so.

This is super convenient except never.

Threads and processes in a Capybara/Selenium session

TLDR: This card explains which threads and processes interact with each other when you run a Selenium test with Capybara. This will help you understand "impossible" behavior of your tests.


When you run a Rack::Test (non-Javascript) test with Capybara, there is a single process in play. It runs both your test script and the server responding to the user interactions scripted by your test.

A Selenium (Javascript) test has a lot more moving parts:

  1. One process runs your test script. This is the process you...

Careful when writing to has_many :through associations

tl;dr: Using has_many associations with a :through option can lead to lost or duplicate records. You should avoid them, or only use them to read records.

Consider this:

class User < ActiveRecord::Base
end

class Party < ActiveRecord::Base
  has_many :invitations
  has_many :users, through: :invitations, include: :user, order: 'users.name'
end

class Invitation < ActiveRecord::Base
  belongs_to :party
  belongs_to :user
  
  after_create :send_invite
  
  def send_invite
  ...

Auto-coerced virtual attributes with Virtus

We've since created ActiveType which has a restricted subset of Virtus' features. It might be enough for your needs.

We sometimes give our ActiveRecord models virtual attributes for values that don't need to be stored permanently.

When such a virtual attribute should contain integer values you might get unexpected behavior with forms, because every param is a string and you don't get the magic type casting that Rails would give you if it ...

Whitelist Carrierwave attributes correctly

Say you have a User with a Carrierwave attribute #avatar:

class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end

When whitelisting the avatar field in the controller, you might do this:

params[:user].permit(:avatar)

But you probably want this:

params[:user].permit(:avatar, :avatar_cache, :remove_avatar)

In this example:

  • :avatar_cache allows a newly upload image to persist through form roundtrips in the case of validation errors (something that isn't possibl...

Alan Klement: Replacing The User Story With The Job Story

I've written about the problem with user stories before. At the time, I found it better to just have the team talk over proposed changes to the product. This worked great when the team had gelled and the product is very mature; however, now I'm working with a new team and building a product from scratch. In this case, because our canvas is blank, we are having trouble getting on the same page when it comes to customer motivations, events and expectations. But today, things have turned around. I've come across a great way to use the jobs to...

Let the browser choose the protocol

Use protocol independent URLs whenever possible so that the browser will choose the protocol related to the protocol which the page is delivered with.

Example issues

  • When your page is delivered via https and you provide a youtube video only via http the most browsers (e.g. Firefox, Chrome) won't display the video.
  • When you deliver your youtube video via https://youtu.be/jyElDp98HdI your test which checks that the embeded video is rendered in the view will fail because your test server doesn't use https

Solution

Let your lin...

Get Moving With Angular 1.2 Animation and Animate.css

Motion is quickly becoming one of the most important emerging techniques in building a quality user experience on the web. Angular 1.2, currently in release candidate form, provides an overhaul of Angular's animation system and makes it spectacularly easy to bring your interface to life.

International Address Fields in Web Forms :: UXmatters

Advice for address forms that work with address structures from multiple countries.

Enable NewRelic monitoring [for Rails] on specific hosts only

If you need to enable NewRelic monitoring on certain machines within the same Rails environment, a simple solution is to utilize the respective hostnames of you machines.

For example, if you have 8 application servers (e.g. app1.example.com, app2.example.com, ...) and want to enable NewRelic on app1 and app2 only, utilize those steps to do so:

  1. Put the attached file into your config directory (config/custom_new_relic_configuration.rb).
  2. Specify on which hosts NewRelic should be enabled (see NEWRELIC_HOSTS constant and list ...

A simpler default controller implementation

Rails has always included a scaffold script that generates a default controller implementation for you. Unfortunately that generated controller is unnecessarily verbose.

When we take over Rails projects from other teams, we often find that controllers are the unloved child, where annoying glue code has been paved over and over again, negotiating between request and model using implicit and convoluted protocols.

We prefer a different approach. We believe that among all the classes in a Rails project, controllers are some of the hardest to...

How to not repeat yourself in Cucumber scenarios

It is good programming practice to Don't Repeat Yourself (or DRY). In Ruby on Rails we keep our code DRY by sharing behavior by using inheritance, modules, traits or partials.

When you reuse behavior you want to reuse tests as well. You are probably already reusing examples in unit tests. Unfortunately it is much harder to reuse code when writing integration tests with Cucumber, where you need to...

Implementing social media "like" buttons: Everything you never wanted to know

So you client has asked you to implement a row of buttons to like the URL on Facebook, Twitter and Google+. Here are some things you should know about this.

0. Security considerations

Each "like" button is implemented by including a Javascript on your site. This means you are running fucking remote code on your page. You are giving Facebook, Twitter and Google+ full permission to e. g. copy user cookies. Check with your client if she is cool with that. Also note that if you're site is suggesting security by operating under HTTPS ...

RailsPanel chrome extension

Chrome extension that shows all info from your rails log (like parameters, response times, view rendering times, DB requests) inside a chrome panel.

Rails 3/4: How to add routes for specs only

If you want to have routes that are only available in tests (e.g. for testing obscure redirects), you can use the with_routing helper -- but that one destroys existing routes which may break a specs that require them to work.

To keep both "regular" and test routes, do this:

class MyApplicationController < ActionController::Base
  def show
    render text: 'Welcome to my application'
  end
end

test_routes = Proc.new do
  get '/my_application' => 'my_application#show'
end
Rails.application.routes.ev...

You don't need each, collect or select in Coffeescript

Working with lists in Javascript is painful because the native Array class is so poorly designed.

One way to reduce the pain is to to use Underscore.js's functions like _.each, _.map or _.select, which unfortunately clutters your code with awkward calls to the _ helper.

Fortunately when you use CoffeeScript you don't need any of that. CoffeeScript has a very versatile for keyword that can do anything that each, collect or select can do. Enjoy!

each

f...

PostgreSQL cheat sheet for MySQL lamers

So you're switching to PostgreSQL from MySQL? Here is some help...

General hints on PostgreSQL

  • \? opens the command overview
  • \d lists things: \du lists users, \dt lists tables etc

Command comparison

Description MySQL command PostgreSQL equivalent
Connect to the database mysql -u $USERNAME -p sudo -u postgres psql
Show databases SHOW DATABASES; \l[ist]
Use/Connect to a database named 'some_database' USE some_database; \c some_dat...

Disable text-transforms in Selenium tests

Using text-transform: uppercase - especially on form labels - can cause you serious headaches in Selenium tests. Sometimes the web driver will see the uppercase text, sometimes it won't, and umlauts will be a problem as well.

Simply disable it in tests, by

  • adding a body class for tests

    %body{'data-environment' => Rails.env}
    
  • overriding the transforms

    [data-environment="test"] *
      text-transform: none !important