Tommy Lee Software development for everyone else

Strange Bug: Safari Parsing

So I spent half a day fixing the following errors. The layout on Rental Cars Search results have been broken on Safari. We suspected that this had to do with Safari’s sppecific handling of divs and invalid HTML.

The General Setup

So the affected code in question looks like this. We have a homebrew JS template that looks and acts roughly like this.

<script type="text/template" id="rental-car-details">
    <div>
       ...
    </div>
</script>

... Somewhere in a JS file...

var details = $('#rental-car-details').clone();
...
details.replace("", priceDetails);
...
resultsBody.append(details);

We have a template, and we build a DOM element, that gets injected after results come back from an AJAX request.

Check the Commit Logs

We confirmed with QA that this was a new bug. Checking the logs, we see only one major commit from the last valid section.

Test By Bisection

I reduced a lot of the code down to make sure that no other divs were affecting it. To make sure that the layout was stable even before this chunk of template exists.

Since this template is loaded via a template tag in Javascript. I started commenting out code and anything irrelevant, to find the part of the load that breaks the code.

The Cause

I started commenting out different parts of the template, and was able to identify the exact line of HTML that causes the problem.

This was that line

<span class="actual-price">
    <span class="dollar">$</span>
</span>
<span class="perday">/</span>

So we kept pairing it down. to eventually get to:

<span class="dollar">$</span>

Yes, so while this is okay in most of the browsers, for some reason, in Safari. When this is injected, this breaks the layout.

Test cases for solutions.

So we did some small tests, seeing if it had something to do with the characters, or the signs. And what we came up was this:

<!-- This *somehow* fixes it -->
<span class="dollar"> $ </span>

<!-- This is still broken -->
<span class="dollar"> $</span>

<!-- This is still broken -->
<span class="dollar">$ </span>

So we found that Javascript Engine in Safari parses the >$< character incorrectly. It required atleast 3 characters within between the span.

Solution:

So to make the least breaking changes possible, I eneded up with the following.

<!-- Safari fix: single dollar sign ($) breaks layout. -->
<span class="dollar">&#36;</span>

I would love to know why this breaks in Safari. But we’ll have to investigate the root cause another day.

Cook and Code 3: Rabbit Season

This meetup was graciously hosted by Dmytro Malikov. He put on his own Cook and Code at his home, with a few of his coworkers here, Eric and Matt.

We tried to implement the single chef / sous chef during this cook and code.

Recipe

Dmytro suggested that we get adventurous, bringing Rabbit from this local latin market.

We ended up doing this recipe:

https://cooking.nytimes.com/recipes/12254-italian-style-braised-rabbit-with-rosemary-and-mushrooms

Snacks

Matt brought Chips and I prepared some Rosemary red potatoes. Really helped keep the motivation up while we tried to figure out the rabbit.

Struggles are real

So we had some issues following this recipe. This was my first time cooking rabbit, and I wasn’t prepare to be a butcher. I forgot to carry my Dad’s Heavy cleaver, and tried sawing away at the bones and spine. Since it was Dmytro’s knife, I feared the back of the rabbit would snap the thin blade.

I had to call over Dmytro to handle the Rabbit. Snap, went the shoulders, the mid back and the hind legs. In my 10 minutes of fiddling, he tore through the bones in 45 grunt filled seconds.

Team Troubleshooting

Dmytro had a little CSS problem. We were able to cast it up on his projector and team debug it.

Results

I didn’t think the Rabbit came out too well. Overcooked it. Even though it was my first rabbit. Jimmy made some backup ribs, and it went over well.

Cook and Code 2: Cooking Ribs

Cook and Code 2

As we make this a monthly tradition, we expndeda to having another member. This time around, we had DmytNro Malikov from Accenture come along.

Dish of the day: Apple flavored Baby Back Ribs

Part of Cook and Code is developing dishes that cook on their own while we spend our time on projects. Jimmy and Charlene brought a rack of baby back ribs, and plan to cook it in a pressure cooker pot.

Recipe

https://recipes.instantpot.com/recipe/easy-bbq-instant-pot-ribs/

We used a modification of the recipe above, but replaced water with apple juice and apple cider.

We did our best to keep everyone involved. Accompanying the ribs, Dmytro and I prepped some vegetable side dishes.

I love that cooking is an activity that everyone can participate. No matter what their skill level, we all have some experience in different areas of cooking.

Jimmy and Charlene had some minor difficulties in cleaning the ribs, pulling away the membrane on the underside. Dmytro, our resident expert in butchery, stripped the membrane cleanly and quickly with his knife skills.

Ribs in Pot

So Tender

The ribs came out very tender. Fell apart the bone. 10/10 would 1000% recommend.

For vegetables. I cooked up some sweet potato fries in the oven, as well as a slaw from Costco.

Ribs in Pot

Meetup Lessons Learned

As our second meetup, we picked up a few lessons to work on in future meetups.

  • Too many cooks
  • Too Complicated to make food
  • Bring Snacks
  • Time to Talk vs Time to Code

Issue: Too Many Cooks

We wanted to bring more focus on the working on the coding and the side projects. We had issues with people butting heads together and not having everything available for cooking available.

We’re seeing this could lead to scalability issues.

Solution: Less Chefs

So instead of having everyone participate in the cook, we’re going to try in the next Cook and Code having a dedicated chef.

We’re calling this having a Lead Chef, Senior Chef as well as having an assistant chef or two.

Issue: Complex prep recipes

I’m used to spending a lot of time prepping and cooking, but this doesn’t work well while we’re trying to optimize for time. So from now on, we’re trying to use a more simpler recipe to cook.

Solution: Simplified recipes

Simple enough. Make easier stuff, simpler items.

Issue: Time to Talk vs Time to Code

So there are some awkward moments where people weren’t sure when it is a good time to talk, or focus on work. This occurred mostly during the early period of coding, or during cooking.

Solution: Dedicated Scheduling

So this was brought up by Jimmy. We probably need to have dedicated time slots so people know when to do what.

We built a template of the schedule, and try to adhere to it.

  • Social Periods: Intro and Eating. Talk as much as you’d like
  • Work Periods: Keep chit chat to relevant projects. Or take chats to IMs messaging instead. Follow the headset rules.

Selfie including Tommy

Cook and Code 1: Cooking and Coding Together

Cook and Code 1

So Jimmy Vo and I have a time management problem. We try our best to balance what time we have to:

  • Expand and maintain our social circle
  • Learn new tech stuff or work on side projects
  • Cook and learn more recipes

So he came up with this brilliant idea: A meetup dedicated to cook and code.

Introducing Orlando’s Cook and Code Together

The concept is simple. Developers meet up. We prep some food together, then code. While the food is either marinating or cooking, we work on some personal development, with fellow developers nearby to bounce ideas or get assistance.

Meeting #1: Beef Burgundy

We chose a simple recipe, that takes a while to cook. I grew up eating my dad’s beef burgundy. Sweet, rich, meaty stew that takes an entire day to cook.

We found a recipe that can be cooked within 3 hours. You can find it here:

Beef burgundy recipe

Cook and Code Raw Ingredients

We divided the labor so that everyone can get to cook asap. I chopped up the vegetables, while Jimmy browned the steak chunks. Browning the meat is important in stews, since it adds additional flavor, and preserves some of the texture.

Cook and Code Raw Ingredients

So we threw in all the vegetables, with the water and bottle of wine into a large pot, and left it to cook. I made sure that it didn’t boil over and stirred it around occasionally.

Cook and Code Raw Ingredients

Coding Goals

For our coding session, we made goals that can be achieved by the end of the session. I try to use [S.M.A.R.T] goals as a framework of choosing what to complete.

For Jimmy, he’s playing with Azure and working on hosting his website.

For me, I’m playing with React to create a form page for one of my side projects.

As with any learning experience, we ran into some issues. I ran into some issues with the ES6 Syntax and how CommonJS module loading works. Jimmy’s azure account was having issues, and couldn’t get access to the right areas for deployment.

Around the hour mark, I check on the stew.

Cook and Code Raw Ingredients

We decided to work on figuring out how to get Jimmy’s project deployed. I remembered that .NET Core could be deployed on Ubuntu, so we went ahead and worked on some basic deployment on Ubuntu.

It was a great learning experience for Jimmy, since he’s from a Windows shop. It was some configurations of nginx, and installing .NET Core CLI to the server.

Cook and Code Raw Ingredients

We pick up a lot of small, unwritten things when we work with others. We learn habits from our friends and family, lessons from our mistakes. I passed down some of my experience doing sysadmin stuff, and deploying stuff on Linux. We learned from repeated errors trying to get the site to run.

In cooking, I made a great mistake with the initial prep for the stew. Instead of seeing the meat slowly get softer, but remain in one piece, the meat started breaking apart. The sweet, winey liquid I expected was non-existent.

I forgot to coat the meat in flour.

So we had braised beef instead.

Cook and Code Raw Ingredients

Lessons Learned for a Successful Cook and Code

So with a completed work, and a full stomach, we call the inaugural Cook and Code Together a success! We learned some new recipes to serve and food prep, and expanded what we knew and had something to work towards in the future.

Some recommendations we have for others:

  • Choose a recipe you haven’t tried yet
  • Divide the labor
  • Set measurable goals

Cook and Code Schedule Template

We follow the following time-line for most cook and codes.

  • 11:00 AM - Event Start and meal prep and cook. Social time and people get together.
  • 11:30 AM - Start coding. Waiting until the food is ready.
  • 02:00 PM - Food is served.
  • 03:00 PM - Clean up.

We have another cook and code coming up soon. We usually keep it small so that the group can work together well. While we can divide up the cooking for just one person, working together on the recipe lets everyone share in the experience.

Fixing Hot Reloads on Vagrant

One of the common issues that I’ve run into virtualizing my development environments is having to restart my server manually.

Whenever I developed locally, everything was fast, and changes appeared on first refresh. But when I used a VM, the frustration of restarting the server killed a lot of my productivity.

The Issue

Many of the hot reloads rely on detecting when the file has changed in your directory. Usually, we have something that watches the directory, and listens for a change.

Whenever a file is changed, the system kernel emits a notification letting a program know that something changed. In Linux systems, we have inotify, on OSX, it’s fsevents.

Since we’re using a virtual machine, our program is only listening to notifications emitted on the virtual machine.

Solution 1: Forward File Change Events

A recommended solution is to add a vagrant plugin to take care of forwarding file events to the VM.

Currently we’re using vagrant-fsnotify to forward events.

After installing the plugin we.

  1. add the fsnotify:true to our synced file directory.

    config.vm.synced_folder ".", "/vagrant", fsnotify: true
    
  2. Restart the machine

  3. Start vagrant fsnotify in a separate tab.

    vagrant fsnotify
    

Solution 2: Polling

An older recommendation is to switch to polling, which detects changes to the modification date occasionally. This was Ruby on Rails’ default detection method until version 4.

This is a fallback in cases where file event updates aren’t available. You can check your dev-server’s start system options, and see if a polling option exists.

I don’t recommend this, since polling takes up more memory and CPU, but if inotify forwarding is unavailable:

In this stackoverflow post, they enabled polling via vagrant rsync-auto.