Code & Iron

Rails

January 14, 2014

Mimicking iOS 7 with jQM and Rails

iOS on the Web A client of mine needed a companion mobile web app that mimics their new iOS 7 app for their non-apple users. Their designer is also hugely passionate about user experience, and has built custom cells, icons, …

  Show More

iOS on the Web

A client of mine needed a companion mobile web app that mimics their new iOS 7 app for their non-apple users. Their designer is also hugely passionate about user experience, and has built custom cells, icons, and has high performance expectations for UI behaviour and response. I knew for him to be happy it needed to be as close as humanly possible to the real deal.

So here’s how to get that nice, smooth, Apple-y feel on the mobile web…

Modifying jQuery Mobile for Fun and Profit

Enter jQuery Mobile to take some of the load off. jQM is a responsive mobile web CSS and Javascript framework that just released stable version 1.4. It aims for a native app experience by offering persistent headers and footers, widgets for common UI paradigms, and AJAX enhancements. However, it maintains a look and feel distinct from all existing platforms. The reasoning behind this is to remain “seriously cross platform” (That list of browsers makes me tired just looking at it). To get around this (admittedly bland) skin, there is an online WYSIWYG editor called “ThemeRoller” that handles the basics. Beyond that, we’re on our own.

Order Matters

Rails 4 uses the asset pipeline, a way of compiling and combining assets to form the eventual CSS, Javascript, and images sent over the wire. It does this by using “manifest files” that send tendrils out to the other folders in your app. More specifically, the “require tree .” in your application.css will find everything under assets/stylesheets in app/ vendor/ and lib/. However, it does not guarantee the order in which they are loaded. This can lead to confusing and difficult to diagnose CSS bugs when dealing with a framework like jQM.

Here are the three CSS components that you need for a fully customized jQM app:

1. Download the minified, gzipped, themeless “structure” of jQM to vendor/assets/stylesheets, or use the jquery-mobile-rails gem.

2. Go to ThemeRoller to paint the broad strokes of your app, and download the original and minified versions to vendor/assets/stylesheets.

3. Finally, overrides of the jQM defaults and your custom CSS or SASS can go alongside your application.css file in app/assets/stylesheets.

Modify your application.css to load in this order:

*= require jquery.mobile.structure.min
*= require my-app-themeroller.min
*= require_self
*= require_tree .

You’re not !important, be more Specific

If you catch yourself rage-clearing your cache, shift/command refreshing, switching browers, or all of the above, you may try the sledgehammer of CSS. Appending !important to a css rule says “disregard any previous, more specific rules, use THIS one”. It has some uses (apparently), but by and large it will make later revisions to your code nightmarish. It’s like try… catch Exception e… swallow in Java. Respect the next developer, just don’t do it.

Instead, if your CSS just isn’t applying, you likely need a more specific CSS selector. CSS cascade and specificity rules are massively complex. Also, jQuery Mobile by convention is filled with very targeted selectors.

So don’t leave it up to chance. Use your Chrome Developer Tools or Safari Web Inspector. Find out the exact CSS selector used by jQM, and override that, it may be much  tighter than you expect. Here’s an example of me nullifying the standard listview borders:

.ui-listview > .ui-li-static, .ui-listview > .ui-li-divider, .ui-listview > li > a.ui-btn {
border: 0px;
}

If it looks like an Apple…

Now that we have our structure set up, what do we modify?

Here are some basic steps to getting that iOS 7 feel out of jQM:

1. Apple uses “Helvetica Neue Ultra Light” for headings and text to achieve that fresh, open air feel. We can mimic that easily on devices with this font pre-installed (Apple products, mainly). However, it’s important to degrade elegantly all the way to sans-serif just in case.

font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif
font-weight: lighter (or 100)

2. Eliminate unnecessary borders, backgrounds, and shadows. Whitespace and sharp contrasting colours are your friends here. Take a look at some of the stock iOS 7 apps for inspiration. Much of this work can be done in ThemeRoller

3. Custom icons on a flat background go a long way and are achieved in jQM via CSS classes with backgrounds

data-icon="carat-right" goes on your list item tag... and then:

.ui-icon-carat-right:after {
background-size: 70%;
background-image: image_url("carat-right.png");
}

So there! Go out into the world and modify jQuery Mobile to your hearts content! Down with the standard skin!

  Posted by Matt Holtom on January 14, 2014
August 27, 2013

Asynchronous Scheduling Options in a Rails Application

The stack behind torontofirecalls.com is not exciting, and that’s the way it should be. There are no outlandish requirements for throughput, response time, or searching. The app will never serve thousands of users at once. Sharding, clustering, caching, eventual consistency; …

  Show More

The stack behind torontofirecalls.com is not exciting, and that’s the way it should be.

There are no outlandish requirements for throughput, response time, or searching. The app will never serve thousands of users at once. Sharding, clustering, caching, eventual consistency; better left to start-uppy folks who are the next Twitter (or have deluded themselves as such).

Yes, it’s Rails.
Yes, it’s on Postgres.

Not much to talk about. So what to contribute?

Well, It’s been an absolute saga to schedule an asynchronous “every 5 minutes” job for this project. From that I ended up with a fairly good understanding of the options out there. Please learn from my pain. An alternate title to this article could be “Why Walled Gardens Eventually Suck”.

Req: Every 5 minutes the app shall update from the City of Toronto, parse the XML, and store the live events. If we miss an hour, that data is lost to us, possibly forever.

Scheduling Options on Heroku

1. Custom Rake Task and Heroku Scheduler
Pros – Free. Very easy setup. Create a custom rake task, and schedule/managed jobs in the web dashboard
Cons – Strictly limited to every 10 minutes, 1 Hour, 1 Day

heroku addons:add scheduler:standard

2. Clockwork and DelayedJob
Pros – Full, expressive DSL. Plays nice with Heroku Cedar. Excellent for applications deployed on multiple machines. Separates scheduling and performance of work (important). Works well when you have hundreds or thousands of jobs at once and need many workers.
Cons – $Expensive$ to run on Heroku, even for a few jobs. Requires one “clock” dyno for scheduling the work, and one “worker” dyno processing jobs. Adds $70 USD /mo to your app.

every(1.hour, 'feeds.refresh') { Feed.send_later(:refresh) }

3. Clockwork and DelayedJob with Workless
Pros – Workless Allows you to sleep a “worker” dyno until there’s something in the delayed_jobs table. Saves almost all the monthly costs of the worker dyno.
Cons – Unreliable. Uses heroku’s scaling API to sleep/awaken your worker(s). Often workers will die silently, or zombie with 0 jobs in the queue. Also, you still need a full-uptime clock dyno to schedule the delayed_jobs, so it still adds $35 USD/mo to your app.

In your production initializer:

config.after_initialize do
  Delayed::Job.scaler = :heroku_cedar
end

Then configure your scaler (to taste) with:

heroku config:add WORKLESS_MAX_WORKERS=1
heroku config:add WORKLESS_MIN_WORKERS=0
heroic config:add WORKLESS_WORKERS_RATIO=1

Scheduling Options off Heroku

* At this point, I got fed up with Heroku and it was time to move on. The Workless gem had failed to scale up/down multiple times. To stay reliable, I was running up an $70 USD/month bill just to process under 300 jobs a day. Not okay. I ported everything to WebFaction and within a few hours had a parallel instance running there.

4. Bare Cron
Pros – Expressive syntax. Full control. Literal decades of proven use. Available on most self hosted servers. Free as in beer.
Cons – Requirement of running the job is not stored alongside your code. Syntax can be intimidating for first time users. Heroku blocks it’s use. Is not ideal for multi-machine deployments/clusters.

Run crontab -e and:

17 8 * * * root echo "This command is run daily at 8:17 am"

5. Cron with Whenever
Pros – Simple, expressive DSL creates/updates jobs in your crontab with the “whenever” command. Requirement and changes to the jobs are stored inline with your code in SCM. Integration with Capistrano available for “update on deploy”. As available, sturdy, and free as cron (for Ruby apps).
Cons – … Heroku blocks its use. Is not ideal for multi-machine deployments/clusters.

In your schedule.rb file:

every :hour do
  runner "SomeModel.ladeeda"
end

Update your crontab using:

whenever -i

Solution #5 has been working very well for me, so the application will finish being ported to WebFaction, likely by the end of the week. It’s now costing ~$10 USD to host instead of ~$80 USD. Hopefully the above comparisons will help you make the right decision early by learning from my 4 mis-steps.

Next writeup will be a quick explanation of how I used the Google Maps for Rails gem and MapIcons by Nicolas Mollet to create the UI.

’till next time…

  Posted by Matt Holtom on August 27, 2013