Wednesday, December 12, 2012

Sinatra Asset Snack: Coffeescript and SASS compilation for Sinatra

Up until recently most of my RIAs have been built using Backbone.JS and Sinatra, using the Sinatra Assetpack gem to handle asset compilation and pipelining. Unfortunately recently I found some performance issues with Sinatra Assetpack.

Generally speaking its great at managing coffeescript and SASS compilation and minification on the fly, however I was finding that as my codebase grew, each time I fired up a server in development, it was taking way to long to clear its cache, recompile and load a page. This was a real drag when working on UX, as this recompilation time made development slow and clunky. I was also finding that even after warming its asset cache, the serving of these assets via assetpack on development and test environments was really preventing quick page loads and was starting to become annoying.

In response, I wrote a simple gem to slim down the asset serving codebase, and handle runtime compilation of coffeescript and SASS in a faster fashion. Its released on RubyGems:

gem install sinatra-asset-snack

At the moment it handles only SASS and Coffeescript compilation, and allows you to designate script bundling into common files (i.e. application.js). For example:

Minification isn't handled yet, mainly as most sites (should) use g-zip compression anyway which means minification is largely a secondary / unnecessary concern anyway.

Should anyone want to write any additional compilers for other syntaxes feel free! The code can be found at https://github.com/benkitzelman/sinatra-asset-snack

Monday, November 05, 2012

S3FS: Mounting an S3 Bucket in Ubuntu


Recently I had an app on EC2 that needed to manage files in an S3 bucket. Normally I would use a gem to handle the uploading etc., but I figured I would give s3fs a crack.

Essentially s3fs allows you to mount an S3 bucket as an external file system, allowing you to manage files transparently as part of the OS.

It was relatively simple to get it working on an EC2 instance running Ubuntu 10.04.3 LTS

OVERVIEW:

 - install the dependencies
 - install s3fs
 - create the password file
 - add the s3 bucket to fstab
 - mount and symlink to deployment dir


Installing Dependencies:
$ sudo apt-get install build-essential libfuse-dev fuse-utils libcurl4-openssl-dev libxml2-dev mime-support


Install Fuse 2.8.4:
$ wget http://sourceforge.net/projects/fuse/files/fuse-2.X/2.8.4/fuse-2.8.4.tar.gz/download -O fuse-2.8.4.tar.gz
$ tar xvzf fuse-2.8.4.tar.gz
$ cd fuse-2.8.4
$ ./configure --prefix=/usr
$ make
$ sudo make install


Install S3FS:
$ wget http://s3fs.googlecode.com/files/s3fs-1.61.tar.gz
$ tar xvzf s3fs-1.61.tar.gz
$ cd s3fs-1.61/
$ ./configure --prefix=/usr
$ make
$ sudo make install


Create /etc/passwd-s3fs:
$ sudo vim /etc/passwd-s3fs

Populate it with
[your_aws_access_id]:[your_aws_secret]

Change permissions:
$ sudo chmod 640 /etc/passwd-s3fs

Add Mount Point:
$ sudo mkdir /mnt/bucket

Add to FSTAB:
s3fs#[bucket-name] /mnt/bucket fuse netdev,default_acl=public-read,use_cache=/tmp,use_rrs=1,allow_other 0 0

Symlink to Mount Point:
$ ln -s /mnt/bucket /[deployed_app_path]/public

FYI ONCE OFF MOUNT COMMAND CMD:
$ AWSACCESSKEYID=[your_aws_access_id] AWSSECRETACCESSKEY=[your_aws_secret] sudo /usr/bin/s3fs [bucket-name] /mnt/bucket -odefault_acl=public-read

Friday, July 20, 2012

3 Character to 2 Character Country Codes

For anyone else who needs to map 3 character to 2 character country codes in ruby, I have provided the following class based on the ISO_3166-1 country code list found at http://en.wikipedia.org/wiki/ISO_3166-1#Current_codes

Saturday, July 14, 2012

Google-api-client Authorizing with an API Key in Ruby

The documentation for the Google RESTful APIs is generally pretty good, however when playing with the google-api-client ruby gem, developed by Google to trawl their APIs, I ran into a few issues, particularly when authenticating using an api key (rather than OAuth).

After installing the google-api-client gem, getting a Google API Key (https://code.google.com/apis/console/), and setting up a custom search account (with its prefs widened to all web pages - http://www.google.com/cse/)....

The following allowed me to trawl google search results (copy paste into irb, then inspect response when finished):

  require 'openssl'
  OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

  require 'google/api_client'
  client = Google::APIClient.new(:key => 'your-api-key', :authorization => nil)
  search = client.discovered_api('customsearch')

  response = client.execute(
    :api_method => search.cse.list,
    :parameters => {
      'q' => 'the hoff',
      'key' => 'your-api-key',
      'cx' => 'your-custom-search-id'
    }
  )

THE MOST IMPORTANT BIT was the :authorization param when constructing he client.... this ensures the api key is used when calling, in preference to oauth. Without it you will get 401 Unauthorized response status everytime.

Thursday, July 12, 2012

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

Somehow my root account lost its 'ALL PRIVILEGES' option, and instead was listing all individual privileges when running

show grants;

As root instead of:
+----------------------------------------------------------------------------------------------------------------------------------------+
| Grants for root@localhost                                                                                                              |
+----------------------------------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*76854B38A7923CC05E7857229F508E66E89D69AD' WITH GRANT OPTION |
+----------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

This was preventing me from assigning all privileges to *.* to other users....
The solution for me (in OSX 10.6.8) was to run in terminal:

mysql_upgrade

which rebuilt my grants table, then after logging into mysql as root, retrying the grant cmd:
GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'localhost'

Monday, June 11, 2012

Sinatra, BackboneJS and CoffeeScript Bootstrap

Just a quick post.... For those who want a quick way to kickstart a ruby / backbonejs app, and maybe do it  in Coffeescript, I added a real basic Bootstrap / project starter to my github account (https://github.com/benkitzelman/sinatra-backbone-bootstrap).

It also integrates Jasmine allowing JS tests to also be written in Coffeescript, which is nice :)

It uses the following tech stack:

GEMS

  • Sinatra
  • Sinatra-assetpack
  • Coffee-Script
  • SASS
  • Jasmine
  • Thin

JS LIBS

  • Modernizr 2.5.3
  • BackboneJS 0.9.2
  • UnderscoreJS 1.3.3
  • JQuery 1.7.2

CSS FRAMEWORK

  • Skeleton 1.1