Streamlined Date/time Selection With Bootstrap

Social Eats' old, awful, ugly HTML DateTime Picker. So many dropdowns!

Pretty regularly while working on projects at Flatiron School I would look at my friend Justin Nazari and, with extreme prejudice and exasperation, I would sigh “Ugh… Dates…”.

We found early and often that dealing with user DateTime input can be a bear. We ran into seemingly countless issues. First we needed to normalize the values being stored from user input, which for us are primarily in the Eastern Daylight Time Zone, against those in the database, which were stored in UTC so we could compare them against one another to display only events that have yet to occur. Then we hacked together a lot of methods to present the date in a pretty fashion, only to find after a morning’s work that Rails Action View Date Helpers already gave us almost everything we needed!

One more big hill to climb was replacing the (awful!) HTML date time picker fields. Emphasis on the S in fields because this archaic input type uses FIVE separate dropdown boxes(!) for Month, Day, Year, Hour and Minute. This is an eye sore and a terrible burden on users, so I finally decided to get rid of it.

To do so, I utilized the Bootstrap3 DateTime Picker for Rails gem, which also requires Moment.js Rails as a dependency.

gemfile
1
2
gem 'momentjs-rails', '>= 2.9.0'
gem 'bootstrap3-datetimepicker-rails', '~> 4.17.37'

And I added the following to the JavaScript manifest in the asset pipeline:

1
2
//= require moment
//= require bootstrap-datetimepicker

And add the following to the application.scss file as well (we were already using Bootstrap so I only had to add line three):

1
2
3
@import "bootstrap-sprockets";
@import "bootstrap";
@import 'bootstrap-datetimepicker';

Previously we were using a form-for datetime_select input field, which is replaced by the following:

New input field for bootstrap datetime selector
1
2
3
4
5
6
<div class='input-group date' id='datetimepicker'>
  <input type='text' class="form-control" name="event[time]" id="event_time" <% if @event.start_time %>value="<%= @event.start_time.strftime("%m/%d/%Y %I:%M %p") %><% else %> value="<%= DateTime.now.strftime("%m/%d/%Y %I:%M %p") %>"<% end %>">
  <span class="input-group-addon">
    <span class="glyphicon glyphicon-calendar"></span>
  </span>
</div>

In assets/javascripts I added the datetime_picker.js file. Here we use the HTML id selector on line 1 above id='datetimepicker' to select the div and give it the properties of the DateTime Picker.

1
$('.date#datetimepicker').datetimepicker().data("DateTimePicker").format('ddd, MMM D YYYY, h:mm A')

Also note that this is where we give .data("DateTimePicker").format() a string as defined by Moment.js. This defines the format our date and time will be not only displayed in to the user in the input, but also how it will be submitted to us. Since we’re just submitting a string of text in this format, but we want to build a DateTime object with that string, this Moment.js format has ramifications on how we associate this time with an event later.

Even before this change we had an instance method parse_time in our Event model, so I wanted to continue using that. It actually required no change, to the method, just the parameters that I was passing in from the previous five-dropdown-menu variant of datetime picker, which had to be parsed themselves.

In order to keep things consistent, here we assign an event’s start_time property by taking our string of text and using Rails' Time.zone.parse method, into which we pass our sting of date and time information.

Event Model
1
2
3
def parse_time(time_as_string)
  self.start_time = Time.zone.parse(time_as_string)
end

The takeaway here was while originally using numerals for Month, Rails would assume I was giving it the date in the order the rest of the world likes (DD/MM/YYYY, smallest to biggest. Makes sense! Just like Metric!) But I wasn’t. So when I entered 7/8/2016 I meant July 8th, but Rails built me a lovely DateTime object for August 7th. Easy solution: use month names in the date picker! Rails can parse them just as well and there will be no mistakes, this time.

What we end up with is a simple, beautiful user experience, with one text entry field and an intuitive selector that pops up at the click of a button.

Social Eats' new, awesome, Bootstrap-ified Date Picker

Social Eats' new, awesome, Bootstrap-ified Time Picker

Client-side S3 File Upload With jQuery File Upload

In my previous career I dealt with a ton of different digital photo upload solutions, so for the second project mode at Flatiron School I was interested in building a project that would teach me the ins and outs of file IO for a web application.

For inspiration we looked to a site our instructor uses to quickly share links with the class, ShoutKey. The basic premise being if you wanted to quickly share a handful of files with a group within hearing distance you could generate a url with a simple slug (a short, human readable, one-word url path). This would give us the opportunity to deal with getting user file input, sending those files to Amazon Web Services S3 storage, and then retrieving the files upon user request, both as single files and as multi-file zip archives.

As our app would be hosted on Heroku, I wanted to find a solution that would fit with that service, so I initially planned to execute uploads from the client-side, so as to not run into any problems with the Heroku dynos resetting mid-upload.

jQuery File Upload presented a way for us to perform these client-side uploads for our Ruby on Rails project.

Heroku’s own guide on this subject was helpful to a point, unfortunately they don’t mention the small matter of file validation, which is relatively important unless you’re interested in having your file storage turned into a Bitcoin miner. Their guide is a great place to get started on the details I’ll fill in here.

Key gems to include:

I like Figaro for defining my secret key values, since it takes just one command line task to push the production keys to Heroku.

First, in the controller we pre-sign our AWS post call.

As part of setting up S3, you also need to set the target bucket’s CORS Configuration, so that the bucket will permit files being sent from your host as an origin. In our application we created a separate S3 bucket that allowed uploads from localhost:3000, and defined these separate buckets in the applicaiton.yml used by Figaro.

application.yml
1
2
3
4
5
6
7
8
9
class EnvelopesController
  before_action :set_s3_direct_post, only: [:show, :edit]

  private

  def set_s3_direct_post
    @s3_direct_post = S3_BUCKET.presigned_post(key: "uploads/#{SecureRandom.uuid}/${filename}", success_action_status: '201', acl: 'public-read')
  end
end

The instance variable @s3_direct_post will be passed to the view for use in our form, and the key: "uploads/#{SecureRandom.uuid}/${filename}" defines the path inside our S3 Bucket where these files will live. This pre-signed POST allows all of our users to utilize my AWS keys to authenticate their uploads to my AWS account.

We send our pre-signed POST into our form as a hash, and then our jQuery File Upload function will use these values to send the file to Amazon.

1
2
3
4
5
<%= form_for(@envelope, html: { class: 'directUpload', data: { 'form-data' => (@s3_direct_post.fields), 'url' => @s3_direct_post.url, 'host' => URI.parse(@s3_direct_post.url).host } }) do |f| %>
    <%= f.label :parchment_url %>
    <%= f.file_field :parchment_url %>
    <%= f.submit %>
  <% end %>

The below jQuery File Upload function sends an AJAX call to AWS based on the pre-signed post and the object a user submits for upload.

The user either drags one or more files to a landing pad which initiates an immediate, AJAX upload to S3. jQuery File Upload has a callback function add which is invoked as soon as files are added to the form file field. It then behaves as a way to iterate over the files when autoUpload: true is set, so you can carry out validations or additional processing of files even though uploads begin immediately.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fileInput.fileupload({
  fileInput:        fileInput,
  url:              form.data('url'),
  type:             'POST',
  autoUpload:       true,
  add:              function(e, data) { // this is the money maker
                      types = /(\.|\/)(gif|jpe?g|png|bmp)$/i;
                      file = data.files[0];
                      if (types.test(file.type) || types.test(file.name)) {
                        data.submit();
                      }
                        else { alert(file.name + " must be GIF, JPEG, BMP or PNG file"); }
                    },
  formData:         form.data('form-data'),
  paramName:        'file',
  dataType:         'XML',
  replaceFileInput: false
});

When the user clicks the “Download all” button, it initiates a ‘GET’ request to a Downloads controller that runs a Zipper service to zip all the requested files into a zip archive, which is saved as a blob in PostgreSQL associated to an envelope. Then the zip file path is sent by send_file as the return of the request and starts a download dialogue with the browser.

A further check against filetype can be carried out by implementing ‘S3 bucket policies’ on the AWS side. This will be expanded upon in a future blog post.

12345? Amazing I Have the Same Combination on My Luggage!

A scene from Spaceballs depicting the inadaqute password of King Roland of Druidia

We often talk about programmers being lazy with regard to how few keystrokes we can type to get something done. Certainly we aren’t alone in that if you look at the annual lists of most popular passwords stolen and made public. Year on year the most popular passwords include “123456”, “password”, “qwerty” and “1qaz2wsx”.

We can’t protect our users from choosing crappy passwords that leave themselves vulnerable, especially when they use “123456” for both their bank and their favorite Beef Fan message board (which, unfortunately, was just hacked for the fifth time last week).

Even if we can’t force the world into using tools like 1Password or LastPass - utilities that let you remember one very strong password to unlock a vault of crazy, impossible to memorize and computationally expensive to guess passwords like ngNbDvnzaQ$Wwwi(,X66gY - we can do our best to protect them in the case of our own database getting hacked by using best practices for storing and protecting their personal information.

Correct Horse Battery Staple

According to the hacker who used a SQL injection to gain access to RockYou.com’s database in 2009, over 30%(!) of websites store passwords in plain text! The hack of RockYou’s database revealed the plain-text passwords of some 32 MILLION users. As Rails developers we know this is maybe the worst idea, especially when password hashing comes pre-installed in every Rails project.

Baked right into Rails' ActiveModel is a SecurePassword class that makes hashed password storage a breeze, so even if your database hits the black market you won’t be opening your users to a world of hurt.

SecurePassword uses the password hashing function bcrypt, which Wikipedia tells us was designed in 1999 by Niels Provos and David Mazières. Bcrypt incorporates hash salting to protect against Rainbow Table attacks, and is adaptive in that over time it can be made to operate more slowly, in order to resist brute-force attacks to increasingly powerful computers.

We include has_secure_password` as a macro on the class that will hold the password in it’s database table, for example in a User class.

1
2
3
class User &lt; ActiveRecord::Base
  has_secure_password
end

By default the class will validate that a password is present, and offers a password-confirmation attribute to check that a user input their password properly at signup. These validations can be overridden by setting has_secure_password validations: false

It also imposes a limit of 72 characters on passwords. Bcrypt has the ability to hash passwords up to 72 characters long, so SecurePassword performs a check to ensure user passwords are properly hash-able. Any characters beyond 72 are simple ignored by the hashing algorithm.

In hashing the password, Bcrypt makes the password unrecognizable by running it through the hashing algorithm, so the password: “12345”  is stored in the database as $2a$04$057HL/XdEJj5RKUVL8J.8.sbzEosI5nFcO4am5V6nZmmKYtAyKI9S 

Sign in

What does it actually mean to “Sign in” a user?

Since HTTP is a stateless protocol, we need to have something to persist a user’s state between requests. For example, without finding a way to persist who is logged in when users navigated between pages they would have to log back in on every page, or they would lose the contents of their cart.

To persist this state we use the concept of a session, a class included in Rails ActionDispatch. A new session will be created by Rails automatically with each new user that connects to an application, or will load an existing session if the user has already used the application. This information is stored locally in a cookie, which opens up sessions to some security vulnerabilities through Session Hijacking, which we won’t get in to today.

The actually act of authenticating a log-in attempt will also be carried out by SecurePassword by calling its #authenticate method on a password submitted as a login attempt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class SessionsController < ApplicationController
 def create
 @user = User.find_by(username: user_params[:username])
 if @user.authenticate(user_params[:password])
 session[:user_id] = @user.id
 redirect_to @user
 else
 errors.add()
 render :new
 end
 end

private

def user_params
 params.require(:user).permit(:email, :password)
 end
 end

The act of logging in to a site seems much fancier than it is in actual implementation. The pages a user does not have access to are not behind a moat, or in a vault, or tucked under a mattress somewhere, their routes are right there next to the pages they do have access too! Admin features, for instance, are likely even written on the same ERB template that Rails uses to render your non-admin user’s homepage! All we’re doing is relatively simple checks on the level of authorization of a user to see what content their account provides access too.

This is the same concept where view content changes after log-in. A navigation element might say “Log In” for a new user, and after logging in a simple if statement switches the view to display “Hello, Will!”.

The authentication process that does this is a two step check against the database where you persist user login information. First, we check if the database has a user with this username. If one doesn’t exist we would send back a generic error message to the user attempting to log in, so as to not provide potential hackers the chance to guess at names in our database and be rewarded with confirmation that they exist.

Secondly, if that user exists we check the password they provided against the hashed and salted password. We pass the provided login attempt password to @user.authenticate as an argument, and if both the user and password match we are returned the user as an object!

Now that we have an authenticated user, we set the session[:user_id], which we will store locally by the user and will check against to determine the current user when new requests are sent. We’ll do this by “poor-man’s caching” the session in a current_user method and checking it’s truthiness in another called logged_in?, and we point to both with helper_method right in the ApplicationController in order to make them available across the controllers.

1
2
3
4
5
6
7
8
9
10
11
class ApplicationController
 helper_method :logged_in?, :current_user

def logged_in?
  !!current_user
end

def current_user
  @current_user ||= USer.find(session[:user_id]) if session[:user_id]
  end
end

We’ll finally make use of that logged_in? method in our views to check which information to show in a view.

1
2
3
4
5
<% if logged_in? %>
  Welcome, <%= current_user.name %>
<% else %>
  <%= link_to "Log In", login_path %>
<% end %>

Parent Programming

While researching the decision to attend a bootcamp I used blogs and sites like Quora to investigate what life might be like at Flatiron School’s 12 week intensive program. A friend had completed the part time, 24-week program at another bootcamp, but I had no personal insight to the more condensed type of program I was interested in.

Along with the often asked, often answered questions most students have about campus life, preparation and so on, there was a big question about a little (7lbs, 10 oz) topic that was going to be very important to my bootcamp life.

What’s it like for a parent to go through one of these programs?

And not just a parent, but a first time parent to a very new (8 weeks yesterday!) baby!?!?

You see, for our family the only way this whole thing was ever going to work was to start and finish my course before my wife’s maternity leave ends. This meant if I didn’t participate in a bootcamp that ran from April to July other considerations would have to be made about child care, which is expensive anywhere but could probably be called extortion here in New Jersey.

So for us, the “only” chance to attend Flatiron School was the April 2016 cohort. So here I am! And I’m surviving! Some days even thriving!

They say at Flatiron that now isn’t a good time to take up new hobbies, and to just focus on coding. But parenting is not optional. I can’t just be absent for 3 months from my baby’s life, and wouldn’t want to be if I could. So how can I make it work?

It takes an incredible support structure, lots of discipline and time management, and a real commitment to the core studies.

For starters, it would be entirely impossible in my mind to do this without my amazing wife. Her commitment to my success at Flatiron is equal to my own, and Monday through Friday she cares for our baby, runs the house, and does lots of work that help keep me on point. You and your partner need to agree in advance on the importance of your focus on coding and learning, and keep a constant line of communication open for when more time is needed. The reality is attending bootcamp means both my wife and I are in bootcamp, and without her help I would’ve already starved AND died from sheer exhaustion. Without a partner willing to carry an extra share of the work at home, you’ll never have the time or energy to bear down and get the work done.

Its also a devil of a thing that my classmates are so awesome, creative and fun. Striking a balance between building relationships with my first group of  programming peers and being home to take over the childcare at the end of a long day of school is a real challenge. Being part of the social fabric of my school is important to me, and I anticipate great friendships and professional relationships with my classmates, but you can only slice the pie so many ways (a problem you face when attempting to serve birthday cake to 31 classmates!)

This means I swing by happy hour for a drink with my class, but after one I’m on the way home to relieve my wife and give her a break from the baby.

It also means setting boundaries on your time and being focused. Goal one is to learn to build amazing web applications, so that has meant a lot of working lunches for me, as well as pulling the laptop out on a crowded train to try and finish up that last lab without missing the last express train home.

Hopefully your commute is shorter than mine (from Northern New Jersey to NYC) but if you’re on a train for 45 minutes like I am that’s another opportunity to focus and continue learning. If you can’t stay late, work on the way home. Typically in the morning I’ll read Rails Guides or other documentation, then on the way home I’ll pull out the laptop and try to wrap up some labs

For me, it’s an important part of being a parent and partner to be home when I walk in the door. That’s the agreement my wife and I have on weeknights: school has already had me from 7:30 am when I start reading on the train, to 7:30 pm when I put my laptop away and get ready to walk home from the station. The time in between is for my wife and baby. Of course, there are exceptions to make for project due dates and for nights like Flatiron Students Present. We also agree to plan for at least one late night a week where I will stay on campus to finish up any lingering work. Here communication is key, so that while your partner carries the brunt of the burden of parenting, you get some cuddle time in with your baby as well.

This, to me, feels like the hardest compromise. I’ve wished for days to be a few hours longer many times already, wanting more time for both home AND to code. The program asks for workaholic levels of time, and with a baby that’s something I simply don’t have to give five days a week.

This opportunity for a career change is for the benefit of my whole family, but I’m not willing to mortgage off even more time with my baby to achieve it. In exchange, I skip the daily ping-pong tournaments in the student center and miss out on the occasional group gathering, but in the end it will be worth it! This journey will be a hard one, but with the support of my family and the amazing staff and classmates at Flatiron School it’s a journey worth taking.

Turbocharging Your Dev Environment

Keep your hands and arms inside the keyboard at all times...

In my past life, I liked keyboard shortcuts and application customizations that sped up my photography workflow. In my NEW life as a Flatiron School student and developer, I LOVE keyboard shortcuts and application customizations!

While (most) every Flatiron and Learn.co student starts out with a pretty solid dev environment on their machine after installing the Learn app, I wanted to dig a little deeper into how to make my applications fly (and look great too!)

Sublime Text and Atom

Out of the box both Sublime and Atom text editors are awesomely powerful. Keyboard shortcuts unlock a ton of speed and control that make these text editors absolutely fly. As developers we’re supposed to be typing, not hunting around with a mouse!

First a primer on Mac Glyphs:

    ⌘: Command
    ⌥: Option or Alt
    ⌃: Control

The following text selection shortcuts are like magic in Sublime and Atom:

⌘ + D :

    Select the current word. Press it again to select the next appearance of the same word. This is REALLY useful for changing a lot of variable names at once.

⌘ + L

    : Select the current line. Same behavior to select subsequent lines.

⌘ + ⌃ + up/down arrow

    : move the current selection up or down. Great for moving a binding.pry or a selected line of code.

⌘ + return

    : make a new line of code after your current line

⌘ + shift + return

    : make a new line of code before your current line

⌘ + fn + X

    : cut the whole current line.

⌘ + /

    : comment out the current line

⌘ + t

        : opens a new tab with a search box. Type in the name of the file you want to open

Also, as our fearless Time Lord leader Steven Nunez has pointed out, this one takes an adjustment in the Mac OS X preferences. In System Preferences -> Mission Control. Remove the keyboard bindings from “Mission Control” and “Application Windows” here:

Now you can use ⌃ + ⌘ + up arrow/down arrow to select lines of code. This is great for quick bulk commenting out of lines.

There are a ton more shortcuts I use regularly, like line indenting and duplicating lines. You can find a whole reference of shortcuts for Mac here.

If you really want to get your shortcut mojo going, step into the shortcut Dojo at Shortcutfoo.com, and practice your shortcuts daily.

Package Control

On top of the included keyboard shortcuts, both Sublime and Atom are highly extensible. Atom comes with this pre-installed in the Atom Preferences ( keyboard shortcut for preferences in any app? ⌘ + comma )

I’ve been playing with both text editors trying to find a favorite, so I’ve played with packages for both.

Sublime Text

First off, you should install Sublime Text Package Control, following the instructions at this link. With Package Control installed you can browse, install, and manage the full repository of packages at packagecontrol.io from within Sublime Text.

With Package Control installed, use keyboard shortcut  ⌘, shift, p to open Sublime’s Command Palette. Now start typing Install Package, hit enter and you’ll have a searchable list of packages available.

Personally, I’ve been using Bracket Highlighter, which shows you the beginnings and ends of your brackets in the gutter (where the line numbers live). This even works for Ruby def and end, class and end, etc.

I’ve also been using SideBarEnhancements, which extends a lot of right-click capability to Sublime that comes default in Atom, like “Move to Trash”, “Open With” etc.

Atom

Atom has many of the same kind of extensions available at this site, but they can also be browsed from within the application, and settings played with in a nice GUI.

Must-haves in my book are minimap, which brings a Sublime Text style minimap to the right side of your editor, so you can zoom around big files, highlight-selected (and minimap-highlight-selected) to help you see all references to the word you have selected, for hunting down typos or just tracing back through your code.

Another powerful Atom package is git-plus. This great package lets you execute git commands without ever leaving Atom, from the Command Pallete ( ⌘, shift, p ). Make a new branch, stage your files, commit and push all without switching to the terminal. Atom’s git integration is already very cool, tracking file changes in the sidebar, and git-plus adds even more power to that relationship.

There’s also countless visual customizations to make in both your text editor and terminal, but those will have to wait for another blog post!

Launchbar or Alfred
Now with 100% more Dash integration!

My personal favorite: Launchbar was a precursor to the Mac OS X Spotlight search (⌘ + spacebar) and is a good deal more powerful. Launchbar integrates with a ton of other applications on your computer to take you to warp speed. Search for a file, and you can move it to a new folder, or launch it with any application that knows what to do with it. Send a text message straight from Launchbar. You can even set up your own search definitions (type g, then space and start typing in the launchbar window for a Google Search, complete with auto-complete!)

There’s a ton of keyboard power to be unlocked with Launchbar (you can use it free as long as you like, but after the free trial it will force you to take a break on occasion).

My favorite new integration is (again courtesy of our Flatiron’s resident time lord Steven) is integration with programming documentation program Dash.

Dash is Ruby-Doc (and any  other programming documentation!) on steroids. If you want to look up the textbook definition of a method, Dash will get you there a million times faster than going to the ruby-doc site.

To travel at warp speed, open Launchbar, type Dash then space, and just start typing what you’re looking for! Launchbar ties right into Dash to get you where you’re going!

And then there’s the simple matter of remapping Launchbar invocation to the Caps Lock key… but that’s a post for another day!

Hello World

Hi! I'm Will, and I'm a photographer

For about a decade that’s how I’ve self-identified. Outside of “human”, “son”, “brother” and “New York Rangers fan” it’s probably the role I’ve inhabited the longest. For about a decade photographer was the most important role I had. Now as a husband and father, that qualification has dropped down the list, and the volatility of the career I built for a decade has grown so severe that I’m taking a big step to shift away from its importance in my family’s life.

In a little over a week I’m starting a new adventure at Flatiron School. I’ll be studying web development with a class of awesome people, learning at lightning speed to build incredible websites and online tools.

Hi, I'm Will. I'm a husband and a father, and I’m going to build amazing things for the web.

I still love photography. For me, family comes first, and success in photography has become difficult without a ton of travel, keeping me away from my amazing wife and beautiful daughter for much longer than I want. This is an opportunity for me to learn a bunch of new skills, and to continue working in a field that is simultaneously creative and technical - to provide opportunity for my family and myself to grow, and to just flat out build cool things to aide our increasingly connected lives.

I’m excited. I’m nervous. I’m anxious. I’m REALLY excited. This is going to be awesome.