Friday, May 27, 2016

Popups on your Popups

We've been using Bootstrap 3 for a lot of the newer screens in our application - particularly our internal, administrator facing screens.  It has been a great framework.  However, the Bootstrap Modals do leave a fair amount to be desired.  You have to write a lot of boilerplate code and then bootstrap has this in their documentation:
Be sure not to open a modal while another is still visible. Showing more than one modal at a time requires custom code.  
To avoid writing boilerplate, we've used the monkey-friendly Bootstrap Dialog javascript library from nakupanda.  This makes showing a Bootstrap Modal as simple as:

Okay, but what if you want to show a modal on top of another modal?  That is custom code!  Oh look, custom code:

A few things are going on here:

  1. When the modal starts to show, set the visibility to hidden.  Bootstrap animates the modal coming in from the top of the screen.  However, the second modal animates in behind the first.  So hide the modal until its completely shown.
  2. To make the second modal come to the foreground, the z-indexes need to be adjusted.  If you dig into Bootstrap 3, you'll find the z-index of the dialog is 50000 and the background is 1030.  So the new modal and back drop need to be in front of those.
  3. The timeout of 100 ms is probably not necessary, but in my application I am displaying an overlay spinner when the link is clicked.  The 100ms makes the overlay show for a minimum amount of time. 

Modals on top of modals are a kludge, and they aren't a great design choice, but when you need them, you need them.
Barf: I know we need the money, but...
Lone Starr: Listen! We're not just doing this for money!
Barf: [Barf looks at him, raises his ears]
Lone Starr: We're doing it for a SHIT LOAD of money!
Maybe in the future, Bootstrap will make multiple modals easier, but I think its justifiable that multiple modals requires custom code.    

Capistrano Deploys without Swap

I work on a Ruby on Rails application that is deployed with Capistrano 3 to Amazon Web Services.  We monitor our site performance with New Relic.  About a month ago, we noticed that our deploys were causing a delay in request processing and a drop in Apdex.

Here is an example of what we saw during a deploy.  The blue vertical lines are the deploy times and the green bar is how long a request spent waiting to be processed.

When we dug into it, we found that our servers were going into memory swap during the deploys.  When we deploy with Capistrano, a new Rails process is started to pre-compile the assets.  This pushes the memory usage over the physical memory limits.   Here is the key graphic from New Relic.  Note the swap usage just after 3:00 pm and the disk I/O at the same time.

You can see in the graph above how memory usage drops after the deploy so the solution to this was pretty straight forward: restart the servers first.

We're using Puma as our web server, so we added these lines to our deploy file.  This causes a phased-restart to be sent before the deploy, freeing memory and allowing the asset compilation to have enough memory to run without using swap.  Since Capistrano is based on Rake, its important to re-enable the phased-restart task after its run, otherwise it will only be run once.

Now our deploys run without causing requests to be queued.  What tricks do you have for zero-impact deployments?

Tuesday, February 10, 2015

Labeling Rails Enums

Rails 4.1 introduced ActiveRecord Enums, a handy little feature that lets you store an integer in a database column, but use symbols or strings in your code.  Until today, I've been presenting these in select boxes with code like this:

This generates a perfectly acceptable select box if you don't need internationalization and the enum names you've picked are good enough to present to the user.  If thats not the case, or you to change the presentation without changing the code, a new helper method leveraging Ruby's internationalization (i18n) features can be a good approach.

Keep reading for how I changed the presentation of enumerations in a drop down without changing my models or renaming the enumeration names.

Tuesday, November 11, 2014

A fun IE9 surprise

As much as I would like to avoid having to deal with IE8 and IE9, sometimes that is just a requirement of the job. Today, I ran across a fun JavaScript bug.

Can you spot it below?

Monday, April 7, 2014

Removing milliseconds in JSON under ActiveRecord 4.0

Rails 4.0 introduced a small bug in JSON generation with this pull request. The output format for times (ActiveRecord::TimeWithZone) in JSON changed to include milliseconds. Sounds good right? Well, not if your API clients crash trying to parse milliseconds. Unfortunately, Rails 4.0 didn't provide a configuration option for the timestamp precision in JSON output. What is a programmer under the gun to do? Upgrade to Rails 4.1 or get out your monkey and your patch and get to work?

Tuesday, March 25, 2014

Model is a poor scope name in Ruby on Rails 4

Upgrading from Rails 3.2 to Rails 4.0 is not a trivial task. Sure, there is a guide, but when you upgrade you'll probably be upgrading a lot of your gems, maybe your jQuery and jQuery-UI versions and then there are all the undocumented unintentional changes that can cause you grief. If you've got a good test suite (you have one right?) you'll catch a lot of these, but some will leave you scratching your head. This one tripped me up for a while: we had a very simple scope stop working in Rails 4.

The scope model below works in Rails 3.2, but fails in Rails 4 when used with an association:

Friday, March 14, 2014

Rails: updating an association through nested attributes does not touch the owner

I was a little surprised to discover that when you update an association through nested attributes, it won't touch the parent record.  It makes sense when you consider that Rails is optimizing by not writing records that have not changed, but if were using updated_at on the model for caching you may be surprised.

For instance: