Zepto 1.1: Moar performance, IE 10+, Deferreds

Posted 8 months back at mir.aculo.us - Home

Mislav and I just released Zepto 1.1, which brings updates across the board. Even if you don’t need to new features, upgrading is worth it for “free” IE 10 support (which makes mobile sites work great on Windows Phone 8) as well as the huge performance speedups for common operations (benchmarks).

Screen Shot 2013-12-05 at 10.09.35 AM

Notable changes

  • IE10+ support
  • Huge speed optimizations for simple CSS selectors (classname, ID) and DOM element creation
  • Provide $.Callbacks and $.Deferred in optional modules
  • Removed fx and detect modules from default build

Ajax

  • New supported $.ajax() options:
    • xhrFields
    • mimeType
    • jsonpCallback
    • username & password
  • Promise interface supported when loading the optional “callbacks” and “deferred” modules:
    • xhr.done(function(data, status, xhr){ ... })
    • xhr.fail(function(xhr, errorType, error){ ... })
    • xhr.always(function(){ ... })
  • Enable mutating Ajax settings in the beforeSend callback
  • Fix JSONP callbacks for errored responses on Android
  • Ensure consistent Accept request HTTP header across browsers
  • Fix $.param() for jQuery compatibility when handling complex nested objects
  • Support IIS JavaScript MIME type
  • Pass “abort” and “timeout” status to global ajaxError event handlers

Event

  • Provide isDefaultPrevented(), stopImmediatePropagation(), and related methods for all events
  • Support the data argument in .bind(), .on(), and .one()
  • Support CSS selector argument in .one() for event delegation
  • Support .on('ready') as an alias for .ready()
  • Enable event handlers on plain old JS objects
  • Many fixes related to event delegation

Data

  • Cleanup .data() values on DOM element removal with .remove/empty()
  • .data() now assumes that numbers that begin with zeroes are strings
  • .removeData() (no argument) now removes all data on the element
  • Enable reading data-* attributes that have underscores in the name

Other updates

  • Support simple DOM property names in .prop(name) such as for, class, readonly
  • Implement the .scrollLeft([value]) method
  • Support setting .scrollTop(value)
  • Fix $(document).width/height()
  • Support fetching multiple CSS values via array in .css(['prop1', 'prop2', ...])
  • Support setting CSS transition delay via delay option for .animate()
  • Ensure that .animate() callback always fires

All in all, our most bestest release yet. A big thank-you to all our contributors for making this awesome! :)

Career Day at San Francisco International High School

Posted 8 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

What inspired you to start making software? For some of us, it was playing videogames. For others, it was the influence of friends or a teacher. Many implemented their first recursive algorithm or user interface when they were teenagers; a smaller number, including me, learned as adults.

Jessie, Devon and I recently had the opportunity to speak about our work with the students of San Francisco International High School. SF International is a unique institution: located in the Mission District, its students are all recent immigrants, mostly from Central and South America and China. Most students come from lower-middle-class backgrounds and are learning English as a second language.

A room full of future surgeons and sales managers

Over the course of two hour-long Q&A sessions with about 200 11th-graders, we were peppered with questions about every aspect of our jobs: Do you enjoy it? What tools do you need to do your work? How much money do you make? We learned that many of the students at SF International aspire to attend university and become, in order of popularity, doctors, accountants, lawyers, police officers and social workers.

We were blown away by the students' enthusiasm and energy. But as software professionals who really enjoy our work, we couldn’t help but feel a little concerned that more students wanted to be sales managers than engineers. Out of all those kids, only one said he wanted to be a programmer. (He already knew C and asked what we do when our websites get DDoS'd.)

Software is boring. Apps are cool.

So why didn’t the 11th graders of SF International consider software to be an interesting or viable career option? Partly because — despite the efforts of people like Mark Zuckerberg and Chris Bosh — programming still seems to have something of a branding problem. When we introduced ourselves as computer programmers or software designers, we were met with polite nods or blank stares. When we said "We make apps like Tumblr and YouTube", the students were excited and impressed.

The image problem wasn’t the only factor. As we spoke with the students, it became clear that there are some persistent misconceptions about programming which diminish its appeal. When we asked students why they didn’t want to be software developers or designers, we'd typically get one of the following responses:

  • "I thought you had to be really good at math to do programming."
  • "But don’t you need to be really smart to learn to program?"
  • "Well, I like working with people. Programmers spend a lot of time working alone."

Reimagining the programmer stereotype

Needless to say, if everyone writing code professionally today could be described as a loner math genius, we would not have the vibrant, diverse, resilient community we do. But familiar programmer stereotypes have persisted in the popular imagination, along with the notion that writing code is a skill only a select few can ever hope (or would want) to learn.

Nonprofits like Girls Who Code and CodeNow are doing a great job of providing resources for kids who want to learn to code. As working designers and developers, we can support this effort by volunteering our time and donating money. As Jessie, Devon and I learned at SF International, we can also think about ways to help local schools update students' perceptions of what it means to be a programmer.

Phusion Passenger 4.0.26 released

Posted 8 months back at Phusion Corporate Blog

Phusion Passenger is a fast and robust web server and application server for Ruby, Python, Node.js and Meteor. Passenger takes a lot of complexity out of deploying web apps, and adds powerful enterprise-grade features that are useful in production. High-profile companies such as Apple, New York Times, AirBnB, Juniper, American Express, etc are already using it, as well as over 350.000 websites.

Phusion Passenger is under constant maintenance and development. Version 4.0.26 is a bugfix release.

Phusion Passenger also has an Enterprise version which comes with a wide array of additional features. By buying Phusion Passenger Enterprise you will directly sponsor the development of the open source version.

Recent changes

  • Introduced the `PassengerBufferUpload` option for Apache. This option allows one to disable upload buffering, e.g. in order to be able to track upload progress.
  • [Nginx] The `HTTPS` variable is now set correctly for HTTPS connections, even without setting `ssl on`. Fixes issue #401.
  • [Standalone] It is now possible to listen on both a normal HTTP and an HTTPS port.
  • [Enterprise] The `passenger-status` tool now displays rolling restart status.

Installing or upgrading to 4.0.26

OS X OS X Debian Debian Ubuntu Ubuntu
Heroku Heroku Ruby gem Ruby gem Tarball Tarball

Final

Fork us on Github!

Phusion Passenger’s core is open source. Please fork or watch us on Github. :)

<iframe src="http://ghbtns.com/github-btn.html?user=phusion&amp;repo=passenger&amp;type=watch&amp;size=large&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="170" height="30"></iframe><iframe src="http://ghbtns.com/github-btn.html?user=phusion&amp;repo=passenger&amp;type=fork&amp;size=large&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="170" height="30"></iframe><iframe src="http://ghbtns.com/github-btn.html?user=phusion&amp;type=follow&amp;size=large&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="190" height="30"></iframe>

If you would like to stay up to date with Phusion news, please fill in your name and email address below and sign up for our newsletter. We won’t spam you, we promise.



Winter's Keep

Posted 8 months back at Mike Clark

Winter's Keep

Seems like a peaceful place to spend a season... or a lifetime.

Episode #423 – December 3rd, 2013

Posted 8 months back at Ruby5

This week we watch, lint, memoize, error handle, say hello to and write more idiomatic Ruby.

Listen to this episode on Ruby5

This episode is sponsored by Top Ruby Jobs
If you're looking for a top Ruby job or for top Ruby talent, then you should check out Top Ruby Jobs. Top Ruby Jobs is a website dedicated to the best jobs available in the Ruby community.

RubyConf 2013 Talks
If you missed out on RubyConf 2013 in Miami a few weeks ago, you’ll be happy to know Confreaks just released the first batch of recorded talks from the conference. I would definitely make time for Object management on Ruby 2.1 by Koichi Sasada who I mentioned on the show recently for his work on the Ruby 2.1 generational garbage compiler. In a less Ruby-centric way, you have to watch Nell Shamrell’s Harnessing the True Power of Regular Expressions in Ruby. Keep an eye on Confreaks since there are many more talks to come.

ruby-lint
Ruby Lint is a linter and static code analysis tool for Ruby. Just like JSHint and other linting tools, it focuses on logic­related errors, rather than semantic errors that are displayed in standard Ruby output. So, if you are trying to use a variable that you haven’t defined, it’ll tell you, instead of outputting a no method error. Ruby Lint tackles undefined methods/variables, unused variables/method arguments and more.

Advanced Memoization
This week, Gavin Miller published a new blog post on memoization covering more advanced memoization patterns. In this post, Gavin shows how to memoize more complex methods like those which have conditionals inside of them or even methods that receive arguments. It’s a quick and useful read, and memoization might allow you to tackle some low-hanging performance fruits in your Ruby applications.

Timetrap
Sam Goldstein just created a neat little gem called Timetrap, a simple tool to help you track time right on the command line. Once you install the gem on your machine, Timetrap will keep track of a list of timesheets. Each timesheet has many entries, and you can check in-and-out of a timesheet as you need to. After you’ve created some entries in your timesheet, you can display the entries, showing information like the date, time in and out, duration, and notes, all right there in your console. Timetrap has built-in support for 6 output formats, including text, csv, ical, json, and ids. There’s even an interface for writing custom formats.

Better Sprockets Errors
Richard Schneeman recently created a gem called Better Sprockets Errors. Its very simple purpose is to raise exceptions in development when you attempt to include assets that have not been white-listed for precompilation. Check out the project's README for links to pull requests on the Sprockets repo.

Idiomatic Ruby
I recently read a new post on the Ruby Love blog about idiomatic Ruby. This post walks through a great refactoring exercise, showing how you can write more Ruby-esque code -- for example, iterating through an enumerable using `.map` instead of `.each`, returning a result with `send`, and cleaning up conditionals using a ternary operator.

Hello Ruby
Linda Liukas — one of the Rails Girls co-founders — is putting together an illustrated children's book about Ruby. She’s writing the story of a little girl (Ruby) and a robot (the computer) to represent and explains some basic Ruby and programming concepts. It doesn't look like the book is anywhere near ready yet but Linda is publishing excerpts on her blog, and you can sign up to be notified about this lovely little project.

Teton Gold and Blue

Posted 8 months back at Mike Clark

Tetons

10 reasons why it’s good for you not to be a dick in open source projects

Posted 8 months back at mir.aculo.us - Home

1. You’re more likely to get what you want.
2. You’re more likely to get what you want.
3. You’re more likely to get what you want.
4. You’re more likely to get what you want.
5. You’re more likely to get what you want.
6. You’re more likely to get what you want.
7. You’re more likely to get what you want.
8. You’re more likely to get what you want.
9. You’re more likely to get what you want.
10. You’re more likely to get what you want.

Sass !default

Posted 8 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

From the Sass documentation:

You can assign to variables if they aren’t already assigned by adding the !default flag to the end of the value. This means that if the variable has already been assigned to, it won’t be re-assigned, but if it doesn’t have a value yet, it will be given one.

This is what it looks like:

$example: 'value' !default;

So using Sass !default is like adding an "unless this is already assigned" qualifier to your variable assignments. But what's the use case for this?

Example: custom styles for a white label app

Recently, a client asked us to create a white label app: they wanted their customers to be able to customize things like colors, logo, background, etc., but to have fallbacks for customers who wouldn't use custom branding. How do you handle this with Sass? Let's step through it.

First, all of these customizable parts are defined in variables.

$brand: company-name;
$brand-color: #0074BE;
$brand-color-alt: #E2EAF2;
$brand-background-1: hsla(0, 0%, 97%, 1.0);
$brand-background-2: transparent;

The variable names are broad enough to use for any customer. If a company doesn't customize anything, this is what they get.

For each customer, we'll create a file with their custom variables. It will use the same variable names, but replace the values. Normally to override variables, you have to define the new value below the original value:

$var_name: 'val';
$var_name: 'new val';

With !default, it's the other way around: we include the brand specific SCSS file first, then we add !default at the end of all our default brand values. This is what our fallback variables look like now:

$brand: company-name !default;
$brand-color: #0074BE !default;
$brand-color-alt: #E2EAF2 !default;
$brand-background-1: hsla(0, 0%, 97%, 1.0) !default;
$brand-background-2: transparent !default;

Optimization

If every client has a customized stylesheet with at least their company name, we need uniquely named files for each of them since client-name-1.scss will live in the same directory as client-name-2.scss.

Files included for client-name-1's account:

@import 'client-1-overrides';
@import 'base-variables';
@import 'header';
@import 'body';
@import 'footer';

To reduce repeated code, we take all of the general imports after our overrides and move them into _application.scss.

Files included for client-name-1's account:

@import 'client-1-overrides';
@import 'application';

So, we've used !default to define the actual default values, and we've overridden them with brand specific values where needed.

What's next?

If you found this useful, you might also enjoy:

Using Polymorphism to Make a Better Activity Feed in Rails

Posted 8 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

You won't find "polymorphic partials" in Rails' API documentation. However, the general programming technique of polymorphism can be applied to Rails partials.

Example: an activity feed for an eBay marketplace

Imagine you are signed into an application similar to eBay. You can buy or sell items on the marketplace. In order to buy an item, you need to bid on it. You see an activity feed that includes bids, comments, and other things that are relevant to you.

Models

We'll use a polymorphic association:

class Activity < ActiveRecord::Base
  belongs_to :subject, polymorphic: true
  belongs_to :user
end

When subjects like Bids and Comments are created, we'll create Activity records that both the seller and bidder will see in their activity feeds.

class Bid < ActiveRecord::Base
  belongs_to :item
  belongs_to :user

  after_create :create_activities

  def bidder
    user
  end

  def seller
    item.user
  end

  private

  def create_activities
    create_activity_for_bidder
    create_activity_for_seller
  end

  def create_activity_for_bidder
    Activity.create(
      subject: self,
      name: 'bid_offered',
      direction: 'from',
      user: bidder
    )
  end

  def create_activity_for_seller
    Activity.create(
      subject: self,
      name: 'bid_offered',
      direction: 'to',
      user: seller
    )
  end
end

In a production app, we'd create those records in a background job. We've simplified here for example's sake. The further benefit of creating them in the background can be seen when we create activities for each of the commenters, which may be a large number for an active marketplace item:

class Comment < ActiveRecord::Base
  belongs_to :item
  belongs_to :user

  after_create :create_activities

  def seller
    item.user
  end

  private

  def create_activities
    (commenters_on_item + [seller]).uniq.each do |user|
      Activity.create(
        subject: self,
        name: 'comment_posted',
        direction: 'to',
        user: user
      )
    end
  end

  def commenters_on_item
    Comment.where(item_id: item.id).map(&:user).uniq
  end
end

Now that we have a clean set of activities in a database table, the SQL lookup is simple:

class User < ActiveRecord::Base
  has_many :activities

  def recent_activities(limit)
    activities.order('created_at DESC').limit(limit)
  end
end

This is the core benefit of structuring our data this way. At runtime, we find the data via a single indexable foreign key, user_id:

create_table :activities, do |t|
  t.timestamps null: false
  t.integer :subject_id, null: false
  t.string :subject_type, null: false
  t.string :name, null: false
  t.string: direction, null: false
  t.integer: user_id, null: false
end

add_index :activities, :subject_id
add_index :activities, :subject_type
add_index :activities, :user_id

Anti-pattern

We've seen alternative implementations that look something like this:

class User < ActiveRecord::Base
  def recent_activities(limit)
    [comments, items.map(&:comments), bids].
      flatten.
      sort_by(&:created_at).
      first(limit)
  end
end

There are a couple of problems with that approach:

  • the number of ActiveRecord objects loaded into memory is large
  • sorting is done in Ruby, which is slower than SQL

Controller

We make our fast lookup:

@activities = current_user.recent_activities(20)

Polymorphic Rails partials

Now, let's show the activity feed in a view:

%ul
  - @activities.each do |activity|
    %li.activity
      = render "#{activity.name}_#{activity.direction}_current_user", subject: activity.subject

Here we render partials with polymorphism. Through the single "#{activity.name}_#{activity.direction}_current_user" interface, we're able to render multiple partials:

  • bid_offered_to_current_user
  • bid_offered_from_current_user
  • comment_posted_to_current_user

When we write upcoming features, we'll be able to render even more partials representing many other interactions, using the same simple structure:

  • bid_accepted_from_current_user
  • bid_rejected_to_current_user
  • etc.

In turn, each partial is small, contains no conditional logic, and results in copy text that makes sense for the user's context:

The Old Man offered a bid of $100 for your Red Ryder BB gun with a compass in the stock, and this thing which tells time.

We can style each partial differently, perhaps showing an image of the items being offered or the avatars of the users who commented.

Nowhere do we do anything like this:

%ul
  - @activities.each do |activity|
    %li.activity
      - if activity.subject_type == 'Bid' && activity.direction == 'to'
        = render "bid_offered_to_current_user", subject: activity.subject
      - elsif
        = # ...

We've replaced an ugly conditional with polymorphism and used a couple of naming conventions to made it easier to add subject types without changing the view logic.

What's next?

If you found this useful, you might also enjoy:

  • Ruby Science to read more about replacing conditionals with polymorphism in Ruby
  • Simple Made Easy to hear about a rigorous definition of "simple" applied to software

The Kid

Posted 8 months back at Mike Clark

The Kid

The kid's a chip off the ol' block.

Improving the Command-Line Postgres Experience

Posted 8 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

Understanding the ~/.psqlrc configuration file, its options, and reading others' ~/.psqlrc files makes working with command-line Postgres more enjoyable.

Changing the prompt

By default, the prompt is a little blah:

$ psql my_database
my_database=#

Let's jazz it up.

There are a lot of options for changing the prompt. You can add colors, domain names, the name of the current database, and more.

\set PROMPT1 '%[%033[1m%]%M %n@%/%R%[%033[0m%]%# '
  • The %[..%] sets the default prompt color to a bold black.
  • %M is "The full host name (with domain name) of the database server, or [local] if the connection is over a Unix domain socket".
  • %n is the database user name.
  • %/ is the database name.
  • %R is "normally =, but ^ if in single-line mode, and ! if the session is disconnected from the database". It's nice to see when you're disconnected.
  • The final %[...%] resets the color to non-bold black.
  • %# is # if you're a superuser, otherwise >.

Here's how it looks on a local database:

[local] gabe@my_database=# SELECT * FROM users;

Changing the prompt, again

Being the smart cookie you are, you've probably inferred that a setting called PROMPT1 implies that there's a PROMPT2. And you're right! You go, Glen Coco. PROMPT2 for you:

\set PROMPT2 '[more] %R > '

PROMPT2 is used when psql is waiting for more input, like when you type SELECT * FROM then hit enter - you haven't typed a semicolon, so psql patiently displays PROMPT2 and waits.

Here's the rundown:

  • [more] is the literal string [more].
  • %R in PROMPT2 has a different meaning than in PROMPT1 - "in prompt 2 the sequence is replaced by -, \*, a single quote, a double quote, or a dollar sign, depending on whether psql expects more input because the command wasn't terminated yet, because you are inside a /\* ... \*/ comment, or because you are inside a quoted or dollar-escaped string."

Here's a contrived example:

[local] gabe@my_database=# SELECT
[more] - > '
[more] ' > name
[more] ' > '
[more] - > FROM users;

Nice.

There's more to life than prompts

Now your prompt is spiffed up, but your ~/.psqlrc can bring still more joy to your life. Here are some options I set, with comments:

-- By default, NULL displays as an empty space. Is it actually an empty
-- string, or is it null? This makes that distinction visible.
\pset null '[NULL]'
-- Use table format (with headers across the top) by default, but switch to
-- expanded table format when there's a lot of data, which makes it much
-- easier to read.
\x auto
-- Verbose error reports.
\set VERBOSITY verbose
-- Use a separate history file per-database.
\set HISTFILE ~/.psql_history- :DBNAME
-- If a command is run more than once in a row, only store it once in the
-- history.
\set HISTCONTROL ignoredups
-- Autocomplete keywords (like SELECT) in upper-case, even if you started
-- typing them in lower case.
\set COMP_KEYWORD_CASE upper

What's next?

If you found this useful, I recommend:

Caching API Requests

Posted 8 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

When making requests to an external service's API, some requests will frequently occur with the same parameters and return the same result. If we cache our request or response, we can reduce HTTP requests, which can improve performance and avoid hitting rate limits.

The APICache Ruby gem is a good choice for caching the API responses (typically JSON) in any Moneta store, such as Memcache or Redis.

However, we don't always need to cache the entire API response. We can save space, avoid adding the operational overhead of Memcache or Redis, and avoid repeating the JSON parsing step if we cache only the URL requested.

In the following example, our app only needs a venue's name, latitude, longitude, and street address. We'll get the data from Foursquare's venue search API by category ("restaurant") and neighborhood ("The Mission").

url = Foursquare.new(category, neighborhood).venue_search_url

ApiRequest.cache(url, Foursquare::CACHE_POLICY) do
  # make a GET to the URL
  # parse JSON
  # create or update venue name, lat, lon, street address
end

The first time this code runs for a venue search for restaurants in the Mission, ApiRequest will save the URL to the database and the block will be executed.

Whenever this runs again for a venue search for restaurants in the Mission, as long as it is within Foursquare's 30 day cache policy, the block won't be executed and expensive work will be avoided.

The internals

It's a pretty simple pattern and the code to make it happen is also straightforward.

Here's the database migration:

class CreateApiRequests < ActiveRecord::Migration
  def change
    create_table :api_requests do |t|
      t.timestamps null: false
      t.text :url, null: false
    end

    add_index :api_requests, :url, unique: true
  end
end

The index improves performance of future lookups and enforces uniqueness of the URL.

Here's the ApiRequest model:

class ApiRequest < ActiveRecord::Base
  validates :url, presence: true, uniqueness: true

  def self.cache(url, cache_policy)
    find_or_initialize_by(url: url).cache(cache_policy) do
      if block_given?
        yield
      end
    end
  end

  def cache(cache_policy)
    if new_record? || updated_at < cache_policy.call
      update_attributes(updated_at: Time.zone.now)
      yield
    end
  end
end

We've kept this model generic enough that it can be used with other APIs, not just Foursquare. We inject a cache policy dependency that must respond to call. This allows us to pass in ActiveSupport's nice Numeric methods like 30.days.ago and have them execute at runtime.

Here's the Foursquare model:

class Foursquare
  BASE_URL = 'https://api.foursquare.com/v2/'
  CACHE_POLICY = lambda { 30.days.ago }

  attr_reader :category, :neighborhood

  def initialize(category, neighborhood)
    @category = category
    @neighborhood = neighborhood
  end

  def venue_search_url
    BASE_URL + 'venues/search?' + {
      categoryId: category_id,
      client_id: ENV['FOURSQUARE_CLIENT_ID'],
      client_secret: ENV['FOURSQUARE_CLIENT_SECRET'],
      limit: 50,
      ll: lat_lon,
      radius: 800,
      v: '20130118'
    }.to_query
  end

  private

  def category_id
    category.foursquare_id
  end

  def lat_lon
    "#{neighborhood.lat},#{neighborhood.lon}"
  end
end

In this example, we chose to build the URL ourselves, using ActiveSupport's Hash#to_query and pulling our client ID and secret in from environment variables.

What's next?

If you found this useful, you might also enjoy:

At The Ready

Posted 8 months back at Mike Clark

Great Gray At The Ready

With talons and wings at the ready, this great gray scopes out the fields for a meal. I went in tight because I loved the contrast between the soft feathers, the face detail, and the razor-sharp talons.

A case against the module design pattern

Posted 8 months back at A Programmer's Perspective

The module design pattern is a particularly popular design pattern used in JavaScript these days. The main reasons for its use are: “Private” variables via closure Global imports A simple example of a module design pattern implementation looks like this: (…)

Read the rest of this entry »

Happy Thanksgiving!

Posted 8 months back at Mike Clark

Great Gray Takeoff

Today I'm also thankful for the birds who aren't turkeys.