Skip to content

Cloud Backup – 2015 edition

Once again I’ve found myself needing to find an online solution to backing up my files.

I found myself in this position a few years ago, and did a bit of research back then, but was lucky that Dreamhost offered 50GB of online backup free with my hosting. They have recently turned off that service 🙁 So I’m updating my findings with current prices and to suit my current needs.

There are a lot of really great backup utilities out there, like carbonate and crash plan, but I can’t use a lot them because I use a NAS drive for all my storage.  It’s super nice and convenient to not have my files tied down to a single computer – but most backup solutions use a bit of software that you install on your computer which won’t work with a NAS drive.

After looking around a bit, like before I think Amazon s3 looks like one of the best options for price and flexibility.  Something new that came up was Amazon Glacier – it’s dirt cheap, but looks really difficult to get working, and I have concerns that syncing won’t be possible with Amazon Glacier.  It’s specifically for long term storage and you store files in packets versus individually, so just grabbing an individual file you accidentally deleted is not possible.  A lot of more straight forward SSH available services were incredibly expensive, like rsync.net that would cost about 2K/mo for 100GB of storage.

I was surprised however, I found out a bit later that both Google and Dropbox offer plans for $10/mo for 1TB – which is the same price for Amazon Glacier. So they’d really be a better option for personal backups.

But, like last time I’ve lucked out with a solution that works for my specific situation. QNAP recently released some software that will automate back-ups with some popular services. This means I don’t need a fully open solution, but just one that is supported by QNAP.

I seriously considered Open Drive for a while because it’s a pretty decent price for unlimited storage, then considered Google Drive for a long time, it did have a cap but was a little cheaper and more flexible and had better file sharing than Open Drive. But, at the very last minute after finally backing up my files and updating my firmware I find out the Crash Plan and iDrive both have apps for QNAP! I had originally wanted to go with Crash Plan, it’s highly recommended by Lifehacker and is unlimited for $5/mo. But after seeing iDrive in there I had to give that a look too. I found some favorable reviews in forums and the jist, at least for me, is that Crash Plan is unlimited data, but only supports one computer and no sharing. iDrive has limited space, but you can have unlimited computers – including mobile devices and Facebook, but a kicker for me is how easy and how much control you have over sharing folders.

Though, the final nail in the coffin was while I was looking up “Crash Plan vs iDrive” I found this offer from iDrive where users comparing the two could get 50% of the first year at iDrive! So, for the first year I get 1TB of space for $30 🙂 I really can’t complain about that, and unless I find some horrendous grievance with iDrive in the future – I’ll most likely end up just staying with them.

Here’s a price breakdown and some notes on of all the services I considered:

iDrive
5$/mo for 1TB (25-50% off first year)
Limited space, but unlimited computers including mobile devices and Facebook, and great sharing features

Crash Plan
5$/mo for unlimited
Unlimited space, but no sharing and only 1 computer

Google Drive
10$/mo for 1TB
Really great sharing capabilities

Drop Box
10$/mo for 1TB

Open Drive
13$/mo  for unlimited
Unlimited – but said to have buggy sharing capabilities

Box
5$/m for 100GB
15$/mo for unlimited

Amazon S3
3$/m for 100GB
15$/m for 500GB
30$/m for 1TB

Amazon Glacier
1$/mo for 100GB
10$/mo for 1TB
Same price as Google & Dropbox for 1TB, but much more complicated

rsync.net
2K/mo for 100GB

BQ Backup
$20/mo for 100GB
$75/mo for 1TB

Rackspace Cloud Files
$10/mo for 100GB
$100/mo for 1TB

AJAX errors explained

I’ve recently finished adding Google Analytics to a mobile App I’ve been working on for some time, and it’s been returning quite a few different error codes from the API.  So, I’m keeping track of them here along with their causes – to make debugging faster and easier in the future.

Status: 406 / Error: Not Acceptable / Error Thrown: Not Acceptable

  1. A server side issue with the response
  2. The session on the server timed out

Status: 0 / Error: error

  1. user was unable to reach the server (most likely connection issue)

Status: 200 / Error: OK / Error Thrown: SyntaxError: Unexpected end of input

  1. Returned JSON was cut off (possibly connection issue)
  2. No JSON whatsoever was returned

Status: 0 / Error: timeout / Error Thrown: timeout

  1. duh, timeout!

Status: 200 / Error: OK / Error Thrown: SyntaxError: Unexpected token

  1. Have HTML returning instead of JSON
  2. Malformed JSON

Status: 401 / Error: Unauthorized / Error Thrown: Unauthorized

  1. User tried to login with wrong username and password

Fats vs Carbs

This is something of a continuation of my “What’s in a calorie?”  article.  Where I dumied down good/bad carbs and fats and looked into why protein is the best thing since sliced bread (which is actually horrible for you).  So I want to continue my oversimplification to carbs vs fats.  There are many many more factors, but I’m trying to pieces things together so with nothing more then a nutrition facts label I can get an educated guess on exactly how good or bad that food is.

After a touch of research, here is my “ranking” of specific macro nutrients:

  1. Protein
  2. Good Fats
  3. Complex Carbs
  4. Saturated Fats
  5. Simple Carbs
  6. Trans Fats

Pretty much every article I looked at described Trans Fat as “the devil” so I think that’s pretty good on the bottom.  Current diet trends are all about Fats > Carbs so I have complex carbs under good fats.  Though, complex carbs/saturated fats seem like a grey area and could easily go the other way.  I’d really like to find something that compares the two in more depth.

This is still a work in progress, but I’m getting the ball rolling.

This time around I got introduced to the glycemic index which is another way to rank carbs. And I already know that not all sugars are created equal, but it seems like the only way to tell the difference is to memorize ingredients.  I don’t have time in my life to give everything such a thorough inspection, but I do have thoughts about putting together a program to assign points to foods based on their nutrition facts to make the process much more approachable.  Pretty much just like fooducate – but with an automatic instantaneous result.

Sources:

http://www.acaloriecounter.com/diet/saturated-fat-trans-fat/
Trans fat is the worst, sat fat not as bad

http://www.olsonnd.com/which-is-worse-fat-or-sugar/
Sugars/simple carbs are worse then sat fat, but better then trans fat

http://www.nytimes.com/2014/09/02/health/low-carb-vs-low-fat-diet.html
Good carbs are worse then good fats

Server side scripting statistics 2015

I’m continuing my study on popularity of different server side languages, and made a few adjustments this year I’ll go over.  This is the exact searches I’m placing on the different job sites:

Keywords: “Ruby on Rails”, “PHP”, “ASP.NET”, “Python”, “Perl”
Location: “San Francisco, CA”
Search Radius: within 30 miles
Posting date: within 30 days

Paying attention to the search radius and posting date are new here, these are the defaults for the different sites:

Monster: defaults to 20 miles with no time limit
Career Builder: defaults to 30 miles within 30 days
Craigslist: doesn’t offer an advanced search so we can’t normalize that
Dice: defaults to 30 miles within 30 days

Both Career Builder and Dice default to 30 miles in 30 days, so I went with that. And there’s nothing I can do to specify the craigslist results, so really only Monster’s numbers will change here.  I did search Monster using the default settings, and the are those numbers:

Default criteria Monster numbers: Ruby 73, PHP 76, ASP 8, Python 135, Perl 9

The numbers are a bit different, but not significantly so.  So, I’m not going to include them in the table, and I don’t believe that’s a significant enough change to skew the results from the numbers from previous years.

One additional thing to note it that I no longer need to omit the . from ASP.NET on craigslist, though doing so didn’t change the number of results.

And, as a note to myself – I found a site that will calculate the totals and percentages for me, which saved a lot of time.

SiteRoRPHPASP.NETPythonPerl
2008 total71 (5%)860 (69%)309 (24%)
2010 Total193 (18%)720 (67%)158 (14%)
2011 Total (2273)374 (16%)1508 (66%)391 (17%)
2012 Total (2085)402 (19%)1396 (67%)287 (14%)
2013 Total (1889)396 (21%)1109 (59%)384 (18%)
2014 Total (2003/5291)412 (21%/8%)1262 (63%/24%)329 (16%/6%)2167 (41%)1121 (21%)
2015
Monster.com (364)64 (17.6%)111 (30.5%)9 (2.5%)175 (48%)5 (1.4%)
Career Builder (346)25 (7.2%)59 (17%)30 (8.7%)154 (44.5%)78 (22.5%)
Craigslist (1281)61 (4.8%)624 (48.7%)44 (3.4%)399 (31%)153 (11.9%)
Dice (1833)425 (23.2%)234 (12.8%)99 (5.4%)756 (41.2%)319 (17.4%)
Total (3824)575 (15%)1028 (26.9%)182 (4.7%)1484 (38.8%)555 (14.5%)

Ruby is higher then it’s ever been, while PHP has gone down a bit.  ASP.NET and Perl took a huge dive – they’re roughly half what they were.  This is the second lowest I’ve seen ASP.  I only have last years number for Perl, so I can’t really deduce too much from this change.

In general over the years it looks like Ruby is gaining popularity, while other languages are just bouncing around.  This suggests to me that the newer Ruby is still finding it’s place, while the other languages are more settled in their positions in the marketplace.

I included totals on the job sites this year too, Dice ended up with the most – which isn’t surprising since it specializes in tech jobs.  With Craigslist right behind – which also isn’t very surprising since it’s the cheapest to list out of all the job sites here.

Social Login with Phonegap, Omniauth, Tokens, and InAppBrowser

For a project I needed to integrate Facebook and Twitter logins to a phonegap app.  I went through a ton of plugins and jsOAuths, but they were all quite cumbersome. I really wanted a simpler approach that would handle Twitter and Facebook at the same time.

This article about Twitter integration with Child Browser got me started in the right direction.  It’s a little dated with Child Browser, so I set out to update it to work with InAppBrowser, but during the process I realized that I could actually handle this issue a lot simpler.  Mostly because I only needed to login and didn’t require any deeper integration with Social platforms.

So after a little more digging I came across this lovely article on cross window communication with InAppBrowser which was everything I needed to take care of business!

In my case, the server is going to be doing all the heavy lifting, and for this project we already had Omniauth set-up for social login and tokens so I only needed to make a few tweaks to get this rolling.

The first tweak was to get it to output JSON for the App.  Out of the box Omniauth will keep track of your params, so I made it return a JSON response when I requested it in the query string like so “/users/auth/facebook?json=true”

Just for example, here how it would look if you were using the standard facebook action for omniauth:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    @user = User.from_omniauth(request.env["omniauth.auth"])
 
    if @user.persisted?
      sign_in @user, :event => :authentication #this will throw if @user is not activated
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      return redirect_to new_user_registration_url
    end
 
    return render :json => current_user if request.env["omniauth.params"]["json"]
 
    set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
    redirect_to "/"
  end
end

The important parts here are:

  • I’m using “sign_in” instead of “sign_in_and_redirect” so I can handle the redirection later down the line.
  • Then I’m adding in “return render :json => current_user if request.env[“omniauth.params”][“json”]” so the callback will output the current user in JSON.

In my case the JSON output for current_user includes a token I can use to integrate with the API.

With that all set you’re ready to capture that JSON in phonegap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
win = window.open(base_url+'/users/auth/facebook?json=true', '_blank', 'location=yes,enableViewPortScale=yes');
win.addEventListener('loadstop', function (e) {
  if (e.url.indexOf(base_url) >= 0 && e.url.indexOf('callback') >= 0) {
    win.executeScript(
      { code: "document.body.innerHTML" },
      function(values) {
        r = values[0];
        r = r.replace(r.substring(0, r.indexOf('{')),"").replace(r.substring(r.indexOf('}'),r.length).replace(/}/g,''),"");
        r = jQuery.parseJSON(r);
        //now r.api_token is available to use however you need in your app
        win.close();
      }
    );
  }
});

This works by:

  1. First opening a window with the social login page “/users/auth/facebook?json=true
    on my app base_url is the domain of the API, like http://api.google.com for example.
  2. Next I’m listening for every-time the page in InAppBrowser finishes loading with “addEventListener(‘loadstop‘”
  3. Then I’m waiting for the URL to have my API’s domain name plus “callback” here “if (e.url.indexOf(base_url) >= 0 && e.url.indexOf(‘callback’) >= 0) {
  4. Once there I use “executeScript” to fetch the document body, which is returned as values[0].
  5. Then I clean the return value of any HTML using replace and substring, then parse that to JSON

After that you can use that token in your App however you need to integrate with your API.