Skip to main content

Mobomo webinars-now on demand! | learn more.

Whether you're new to css layouts or a ninja css warrior we both share one common enemy: The Box Model.

The box-model is the way we calculate the width and height of an object. The W3C modal calculates the width and height by adding the padding and border to the width you specify ( width + padding + border / height + padding + border ). This is a pain because when we want to specify a width to be 400px wide, we first need to subtract the difference of the padding and border to make a 400px wide box. If we had a border of 10px and a padding of 20px, the width would be 340px wide (400 - 20 - 40 = 340px).

IE6 has a quirk where its box model calculated the width with the border and padding inside. When I started out as a developer I thought this was odd as other browsers calculated differently. This is how the border-box calculates the width. This really comes in handy when used for responsive design and fluid grids!

Box-sizing does take two values. First, the border-box as we have described above where the padding and border are inside. The second value, which is commonly used across browsers is content-box specified by CSS2. The padding and border are included to the width and height.

box-size comparison

Using box-sizing you can have fluid grids and keep all your gutters and borders inside. This makes it easier when starting out with responsive web design. We have begun using the border-box value for the box-size property in our recent Github pages (Omni Auth, Green Onion, Grape). Take a look at them as examples of how simple designs can be responsive with box-sizing: border-box property.

You can also play with sample code at Codepen.io.

Browser Support

  • Firefox 1-3, un-prefixed in current version
  • Safari 3, un-prefixed in current version
  • IE8+

code

  * {   -moz-box-sizing: border-box;   -webkit-box-sizing: border-box;   box-sizing: border-box;   }

By using the * you make all elements on the page use the box-sizing property.

If you have not started using box-sizing, I highly recomend using it in your projects. For the vetrans that know the old box modal this will help you with responsive web design. As mobile takes over, responsive design will become common practice, and the box-sizing property will become your new best friend!

Categories
Author

If you're running any kind of service that uses e-mail as a communication method (which is just about everyone) and you want your users to be able to take some kind of action from the email (as just about everyone does) then you should be using Signed Idempotent Action Links. Now I know what you're thinking, "Signed Idempotent Action Links? But EVERYONE knows what those are!". I know, but here's a refresher anyway (ok so I made up the term, but it's descriptive!).

They are links that perform an action (such as "Delete this comment" or "Add this to my favorites") with an included signature (that associates the URL to a specific user and verifies parameters) and are idempotent (meaning that accessing them multiple times will end in the same result). In a nutshell, they are URLs that you can click through from an email and they perform a desired action:

  • whether or not the user is signed in
  • without any additional button presses or clickthroughs

So now that we've gone over what we're dealing with, why would you want to use them? Well, because not everyone is logged into your service when they're checking their email. In fact, if they're checking it from a smartphone or a public computer they most likely aren't logged into your service unless you're Facebook. It is the friendliest way to allow your users to perform simple actions through email.

Calm Down, Security People

Of course the reason not to use SIAL is that if a link can perform an action without requiring a login then, well, anyone can perform that action if they have the link. Very true! However, this problem is not enough to completely bar the use of SIAL because:

  1. These links are being sent to people's email accounts. If your email account has been compromised, you're already in way more trouble than SIAL can give you.
  2. Developers can counter this issue by making any SIAL action reversible. Have a "Delete" link? Make sure you have an "Undelete" function in your app somewhere.
  3. Convenience trumps security for many applications. Sure, don't use SIAL to initiate wire transfers or for anything that costs money, but most applications have plenty of non-world-ending actions that can benefit from instant access.

How to Use SIAL

There are two important things to consider when using SIAL:

  1. You MUST be able to verify any actionable content in the URL.
  2. You SHOULD only allow the single action via the SIAL URL. Do not log the user in from a SIAL action.

So, how do we implement something like this? Well, it's really quite simple. Here's a method similar how it was implemented for Qup.tv. First, we create the means to sign an action in a User model:

require 'digest/sha1'  class User   # ...    def sign_action(action, *params)     Digest::SHA1.hexdigest(       "--signed--#{id}-#{action}-#{params.join('-')}-#{secret_token}"     )   end    def verify(signature, action, *params)     signature == sign_action(action, *params)   end end 

What we're doing here is creating a SHA1 hash of a string that is built using a known formula and includes all of the elements needed for the action:

  • id is the id of the user
  • action is the name of the action that we're taking. For Qup the action might be queue, watch, or view.
  • params are any additional parameters that alter the outcome of the action. Again, for Qup this could be the id of the title to queue, watch, or view.
  • secret_token is a unique token for the user that is not shared publicly anywhere. You can generate this using SecureRandom or find another way to implement a secret token. This should not be something like a user's password hash as it should not be determinable from any info a user would know.

So now that we have these methods for our user, how do we go about creating the actual URLs that we'll be using? Well, if we have a simple Sinatra application we can do it like so:

helpers do   def authenticate_action!(signature, user_id, action, *params)     @current_user = User.find(user_id)     unless current_user.verify(signature, action, *params)       halt 401, erb(:unauthorized)     end   end    def action_path(user, action, *params)     "/users/#{user.id}/#{action}/#{user.sign_action(action, *params)}/#{params.join('/')}"   end end  get "/users/:user_id/favorite/:signature/:item_id" do   authenticate_action!(params[:signature], params[:user_id], 'favorite', params[:item_id])   @item = Item.find(params[:item_id])   current_user.favorites << @item unless current_user.favorites.include?(@item)   erb :favorite_added end 

As you can see, all we're really doing here is:

  1. Creating a helper that will display a 401 unauthorized message if the signature provided in the URL does not match the proper signature for the provided user.
  2. Creating a helper that will help us to generate URLs for our actions.
  3. Showing an example of how one such action could be built.

Notice that in this example I am making no use of session variables or any kind of persistent state. In fact, you should make sure that you ignore all such variables. If another user is signed in at the moment, the link should still work for the signed user.

One other thing to notice is that the item is only added to favorites if it isn't already there. This gives the action idempotence: whether you run it once or 100 times the result is the same, making sure that the item is in the user's favorites.

SIAL is not a technique that you will use in every instance, but the benefits for the user can be big in terms of convenience, and it's often the small conveniences that make a big difference when developing software that people love.

If you liked this post (or didn't) and you use Netflix Instant, go check out Qup and get email alerts (with Signed Idempotent Action Links) when new titles are added.

Categories
Author

This past weekend I participated in Hack the Midwest, a Kansas City hackathon. The event was a huge success drawing a crowd of around 100 developers. As one of the visiting developer evangelists said, it was a great turnout for a New York hackathon, much less one in the midwest.

At the competition I built Qup.tv, a simple service that will send you email alerts when Netflix adds new titles to its streaming catalog. I was lucky enough to win top honors at the event, but this wasn't my first rodeo. With three Rails Rumbles, two Node Knockouts, and a Startup Weekend under my belt I'm beginning to get a sense of what works and what doesn't. So here's my list of things to keep in mind when competing in a hackathon:

1. Have a Layered Strategy

You will never accomplish everything you set out to complete at a hackathon. Something at some point will take ten times longer than it was supposed to, so you need to plan for having multiple goals any of which could end up being the final product. Your first stage should be something that you expect you can complete in well less than half the time allotted. For example, here was my layered plan for Qup:

  1. Users can sign in with their Netflix account and will receive emails of the latest Netflix releases
  2. Users can add items to their queue or watch them with one click from the email. For queueing, users should not have to be logged into Qup or Netflix
  3. Users can filter based on Netflix rating, Rotten Tomatoes score, and exclude genres they don't want updates about
  4. Track usage activity to be able to show which of the titles are most popular
  5. Add in support for Amazon Prime Instant Videos and/or Hulu

Even though my app won I only got through about half of what I thought I might be able to accomplish in 24 hours. I also ended up doing a decent amount of work tracking genres and usage activity which didn't show up in the final product at all because I didn't have time to polish and expose it. Which brings me to tip #2.

2. Cut Everything That Doesn't Work Well

It's a hackathon so judges will excuse a bug here and there, but regardless of how cool or important a feature is if it is likely to glitch more than 20% of the time you should cut it out of your final product. A smaller, less featured, but smoothly working project is going to win over a more featured but buggy project.

This applies to any kind of live demo in addition to a "go check it out" URL. Don't demo anything that the judges can't do themselves when they use the app (unless they don't get to use the app, in which case you'd better work hard to make sure your demo runs glitch free).

3. Style First, Substance Later

You can ignore this tip if you're working on a team with a dedicated designer (and how lucky for you if you are), but you should avoid the temptation to dive straight into the depths of coding when you start your project. Instead here are the things that you should do first:

  1. Create some kind of logo for your project
  2. Create the best looking landing page you can, even if it takes much longer than you'd like to spend on it
  3. Create accounts on Twitter, Google Analytics, UserVoice, etc. Anything you'll want to have at the end create at the beginning
  4. Buy domains, hosting accounts, etc. and get them all set up how they'll need to be

Why waste your time on all of these technicalities? Because the landing page is the first impression of your app that any judge will get, and if it doesn't impress them then you're already fighting an uphill battle. I spent perhaps the first hour and a half to two hours out of the 24 hour hackathon building the landing page for Qup, but that meant that I wasn't scrambling to make an ugly slapped-together mess pretty at the last second.

Integrate design and style as you go because when there's 45 minutes left you're always going to choose fixing a bug over polishing the interface.

4. Deploy Early, Often, Always

As soon as you have your pretty landing page and logo you should get your production environment up and running. If you can, use a Platform-as-a-Service like Heroku to take the operations burden off of yourself: you'll have enough to worry about on the app side.

Once you have a working production environment, make sure that you're deploying and smoke testing your code on a regular basis. There are almost always small (or large) problems that don't show up locally but do on a production box.

You'll notice that many of these tips have been about avoiding doing things at the end. That's because regardless of how carefully you plan you will be scrambling to fix earth-shattering bugs in the final minutes of the competition. It's tempting to put a tip like "don't deploy anything in the last two hours" because I've been burned multiple times by breaking something big while fixing something little at the last minute, but I won't. Instead you should be deploying SO FREQUENTLY that any fixes in the last minutes can be rolled back if they are deemed to be a bad idea.

5. In Presentations Show, Don't Tell, and Stop When You're Done

Your tech stack and the different ways you tackled the engineering challenges that your project presented are all very interesting. To you. Judges don't care, judges don't give a s**t. Instead keep your presentation focused only on the cool things your project does for the end user.

At Hack the Midwest we only had three minutes for presentations. Nearly everyone was running right up against the buzzer, so I was nervous. When it was my turn I gave maybe 20 seconds of exposition and then jumped right into the demo. I showed off my key features, anxious that any second I'd be cut off. In reality I probably still had a minute or more left. But rather than continuing to vamp about how I piped an RSS feed into an API queue fetch pool, I just stopped. I had already made my pitch, and I wouldn't do anything but hurt my chances from there.

Developers like to believe that code can speak for itself, and that's actually pretty true. However if your hackathon includes a presentation component you must speak for your code, so don't completely ignore a plan for presenting.

Do Something YOU Want

One last bonus tip is this: hackathons are about having fun, not winning. I've done seven of them and last weekend was the first prize of any kind that I've won. The beauty of the hackathon is that it gives you the opportunity to prove your mettle against yourself as much as against anyone else. It lets you say "what can I truly accomplish in X hours?". For me, this is a powerful drive and one that I'll gladly challenge myself with again and again. You can expect to see me in most every hackathon that comes around; I'm hooked.

Categories
Author

I've got 99 problems but a redirect ain't one

What do you get when you discover you setup a route incorrectly ages ago? Why, a redirect of course! And a blog post with some handy redirect code that you might find useful one day!

The Situation

Our blog posts were routed like so:

  match '/:year/:month/:day/:id' => "posts#show", :as => "blog_post",         :requirements => { :year => /d{4}/, :month => /d{2}/, :day => /d{1,2}/ } 

Which technically works just fine... except that the URL of a post ends up as this:

When I'd really rather have the URL as this:

If I had just setup my routes for the first time today I would simply change it to this (to include 'blog' in the url):

  match '/blog/:year/:month/:day/:id' => "posts#show", :as => "blog_post",         :requirements => { :year => /d{4}/, :month => /d{2}/, :day => /d{1,2}/ } 

But since posts had been routed that way for quite some time, I needed to add a redirect to ensure that older links to posts that were floating around in the ether would still work.

So then I was all like, "Sweet! @merbist mentioned that redirects can be done in the routes in Rails 3! Easy Peasy!"

Thus, I added some code to the routes file that looked like this:

match '/:year/:month/:day/:id', :to => redirect('/blog/:year/:month/:day/:id'), :as => "blog_post",        :requirements => { :year => /d{4}/, :month => /d{2}/, :day => /d{1,2}/ } 

And then Rails was all like, "Oh no she didn't!"

NoMethodError in PostsController#show  undefined method `published_on' for nil:NilClass Rails.root: /Users/renaebair/workspace/intridea/newsite  Application Trace | Framework Trace | Full Trace app/helpers/blogs_helper.rb:23:in post_link' app/controllers/posts_controller.rb:23:inshow' Request  Parameters:  {"requirements"=>{"year"=>/d{4}/, "month"=>/d{2}/, "day"=>/d{1, 2}/}, "year"=>":year", "month"=>":month", "day"=>":day", "id"=>":id"} 

And then I was all like, "Must not have the syntax down. No problem, Google can help!"

And after several dead ends and poor implementations I had to step back.

The Solution

Finally, with my coder ego sulking at subterranean depths, I pulled together the humility to ask for help; I pinged Michael Bleigh, who is a very busy guy but never ignores a coder's plea for help.

In less than 30 seconds he sent me a working solution, which I now present to you:

  match '/:year/:month/:day/:id',          :to => lambda{|env|            Rack::Response.new(['301 Permanently Moved'], 301, {'Location' => "/blog#{env['PATH_INFO']}"}).to_a         }, :as => "old_blog_post", :requirements => { :year => /d{4}/, :month => /d{2}/, :day => /d{1,2}/ } 

As you can see, he embedded a Rack reponse in the route using a lambda. This is important because the route file is only loaded once , right when the app starts up. Putting the redirect code in the lambda ensures that the Rack response will be evaluated anytime that route is matched. When it's matched the Rack response throws a 301, indicating the page has a new home and redirects to the new home. It's important to use a 301 code "Permanently Moved" because otherwise you'll lose a ton of link "juice" (eww). Click here for more HTTP status code definitions.

And there you have it - a juicy snippet of code for all your redirect woes!

Categories
Author

What do you do when you cannot start a new server session because the address is already in use? It happens to the best of us, such as this morning when I exited my terminal without first quitting the rails server. I found myself faced with this error in my new terminal when trying to spool up a localhost:

 ? ./script/server => Booting WEBrick => Rails 2.3.11 application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server [2011-12-22 11:41:15] INFO  WEBrick 1.3.1 [2011-12-22 11:41:15] INFO  ruby 1.8.7 (2011-02-18) [i686-darwin10.7.0] [2011-12-22 11:41:15] WARN  TCPServer Error: Address already in use - bind(2) Exiting

I Googled around for some information, but ultimately Paul was able to troubleshoot my issue over corp chat. Here’s the solution that worked:

Enter this into the terminal:

 lsof -i TCP:3000

It will yield a result that might look something like this:

 renaebair@siren ~/workspace/intridea/newsite (master)  ? lsof -i TCP:3000 COMMAND  PID   USER       FD     TYPE     DEVICE     SIZE/OFF    NODE   NAME ruby   68780   renaebair   6u    IPv4     0x10898278     0t0      TCP     *:hbci (LISTEN)

Grab the process number (a.k.a. PID) (in this case it was 68780) and then type “kill #{that_pid}”:

 kill 68780

Then try restarting your server and all should be well!

Paul here with a few quick words about what’s going on in this case:
When Renae closed her terminal session with the rails server still running, the server process became orphaned. It was still active and serving pages on localhost:3000, but without a controlling terminal window, Renae was not sure how to stop it. Also, because it was bound to port 3000 it prevented a new rails server from starting on the same port. The lsof command is used to list open files, in this case the pseudo-file for tcp port 3000. (It can also be used to figure out what processes are logging to a file lsof log/development.log. This is sometimes useful when a plugin is writing to the rails log instead of its own log file.)

Once we have the PID for Renae’s orphaned process, we can send a signal to it, telling it to close itself. The kill command is the mechanism for sending that signal. To be polite, we first send a TERM signal, which roughly means, “Would you please finish up what you’re doing and close, dearie?” If that doesn’t work in a reasonable time, we can send a KILL signal (side note: I find it unfortunate that the signal and the command share a name, but that precedent is older than I am) kill -9 some_pid which translates to “KILL IT WITH FIRE”. As in real life, being less polite may result in needing to handle some cleanup yourself.

There is a slightly easier option. If we suspect that port 3000 is bound to a rogue rails process, you can use the killall command as a more “shotgun” approach. But what fun is that?

Categories
Author
1
Subscribe to Protip