Skip to Navigation | Skip to Content

Kelli Shaver

I'm a software developer who specializes in building great web applications, with a passion for future-friendly code, human and device accessibility, and open data.
I've moved! You should go here

The Game Cabinet: Seasons

gamecabinet:

image

This is a newest addition to my game collection; one I’ve only had for a couple of weeks. I have to say, I like it a lot. Some of that is probably new game excitement, but Seasons has a lot of good things going for it.

The theme of the game is simple: You’re a wizard competing in a…

(Source: )

Say hello to CSS Simple

Last night, I started building CSS Simple - a lightweight CSS library for building clean interfaces. 

To be quite blunt, I was getting tired of all of the bloat around other CSS frameworks.

Grid systems feel cumbersome and aren’t always necessary (and often aren’t mobile-first). Heavy ties to jQuery adds a bulk and complexity that isn’t always needed. Reliance on a few COMPASS mix-ins means you need the whole COMPASS framework installed to edit anything.

There are a lot of good reasons why these things are beneficial and many cases where they are necessary (or at least very helpful), but there are also a lot of times when they’re just overkill.

This is where CSS Simple fits in.

I’ve only worked on it for a few hours, so in a lot of ways, it still feels like a library for prototyping. It’s also Webkit-only at the moment. Those two things may change, or they may not. It depends on how much I have time to work on it and how my needs change over time. We’ll see.

Even if it remains a Webkit-only library for UI prototyping, I still think there’s value in that.

You can see it in action here and view it on Github here.

Browser Scratch Pad One-Liner

I saw a few of these floating around a while back. The idea is to create a data URL one-liner to turn a browser tab into an editable scratch pad for taking notes, or writing whatever. It’s kind of handy.

Here’s my take (Tumblr mangles the URL if I try and link to it):

data:text/html;charset=utf-8,<title>Text Editor</title><link rel=”shortcut icon” href=”http://g.etfv.co/http://www.sublimetext.com”/><link href=”http://fonts.googleapis.com/css?family=Droid+Sans+Mono” rel=”stylesheet” type=”text/css”><body OnLoad=”document.getElementsByTagName(‘body’)[0].appendChild(document.createElement(‘p’).appendChild(document.createTextNode(”))); document.body.focus();” contenteditable style=”font-size:16px;font-family:’Droid Sans Mono’, sans-serif;max-width:80%;margin:2em auto;padding:2em;background-color:#222;color:#f3f3c4;line-height:1.5em;-webkit-text-shadow:1px 1px 1px #000”>

RESTify Your API

This bugs me, too. Hint: If your API has the words ‘new’, ‘edit’, ‘view’, ‘delete’ or similar in the URL structure, your API is not RESTful.

I ordered a couple of new games for the collection tonight. I&#8217;m looking forward to getting these off the UPS truck Wednesday, but I really need a bigger game cabinet.
I ordered a couple of new games for the collection tonight. I&#8217;m looking forward to getting these off the UPS truck Wednesday, but I really need a bigger game cabinet.

I ordered a couple of new games for the collection tonight. I’m looking forward to getting these off the UPS truck Wednesday, but I really need a bigger game cabinet.

Today I got a new laptop bag. I&#8217;ve been wanting one for a while. The Lowepro bag I&#8217;ve had for a few years now is nice and has held up really well. It&#8217;s just a bit larger than I would like. This small Timbuk2 bag, however, is perfect for the small amount of things that I carry.
Today I got a new laptop bag. I&#8217;ve been wanting one for a while. The Lowepro bag I&#8217;ve had for a few years now is nice and has held up really well. It&#8217;s just a bit larger than I would like. This small Timbuk2 bag, however, is perfect for the small amount of things that I carry.

Today I got a new laptop bag. I’ve been wanting one for a while. The Lowepro bag I’ve had for a few years now is nice and has held up really well. It’s just a bit larger than I would like. This small Timbuk2 bag, however, is perfect for the small amount of things that I carry.

Jack's: Let's reconsider our "users"

jacks:

us·er
/ˈyo͞ozər/

Noun
1. A person who uses or operates something, esp. a computer or other machine.
2. A person who takes illegal drugs; a drug user.

Synonyms
consumer

During a Square Board meeting, our newest Director Howard Schultz, pulled me aside and asked a simple question.

“Why…

CORS headers with Devise

Yesterday I set about to add a small JSON API to an already-built Rails application that uses Devise for its authentication system. This was simple enough to do by enabling token-based authentication and rendering a few rabl templates via respond_to blocks (well, I say “was” but I’m actually not finished yet - that’s the gist of it, though, I just have more of them to do).

However, I did hit a small stumbling block when it came to enabling CORS headers. For those of you not familiar with them, CORS headers are the magic sauce that lets other applications, say, a JavaScript client hosted on a different server, fetch and parse JSON directly from your web server, effectively disabling same-origin policy restrictions that the browser places on remote JavaScript.

In order to send these headers in my Rails application, I added a couple of before filters in my Application controller; one for the pre-flight (essentially a silent request made by the browser prior to an AJAX call to ensure that it has permissions to make the call) and one for the AJAX call itself.

This all worked fine and I was able to log in by POSTing to the Devise session controller, which would then give me my JSON user object, with its included authentication_token in return.

However, whenever I would enter an incorrect email/password combination, rather than sending the error object, the server would return a 401 Unauthorized header, without sending the additional CORS headers.

The reason for this turned out to be that Warden, the bit of Rack middleware that Devise uses for authentication, was handling the failed request itself, before ever letting it pass through to the rest of the application (for, I assume, security reasons).

One solution was to use the Rack CORS gem and inject it into the application before Warden. This would work great, except that I have, on more than one occasion, had issues with this gem and tonight was no exception.

Fortunately, what I wanted to do was fairly simple. I just wanted to return CORS headers for everything. I’ll let my authentication system limit access, not my HTTP headers. That meant that those headers didn’t need to be very restrictive or dynamic.

So I wrote a small piece of middlware of my own:

# lib/cors.rb
class Cors
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)

    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'DELETE, GET, HEAD, OPTIONS, POST, PUT'
    headers['Access-Control-Max-Age'] = "1728000"

    [status, headers, response]
  end
end

Next, it was simply a matter of using it, and inserting it where it needed to be, via my app/config/application.rb file.

module MyApp
  class Application
    # ....

    config.middleware.use "Cors"
    config.middleware.insert_before Warden::Manager, "Cors"
  end
end

Now response headers sent by Warden will be injected with the CORS headers created by our little custom bit of middleware, and thus failed login attempts will now return a proper 401 authentication error, rather than hanging as a cancelled request due to a failed pre-flight check.

If you need a more robust solution, it’s probably worth checking into Rack CORS, but this could also easily be extended by loading YAML config files containing lists of allowed origins or allowed resource URLs and returning headers conditionally.

Page 3 of 16

Previously

Recent