How to specify Fancybox2 options to manually open() a box (the docs are wrong)

Fancybox is a superb tool for adding a lightbox-style popup to your web app. And Fancybox2 (the paid version) adds some very nice features and occasional updates, all well worth the trivial cost. The docs are incorrect however as to how to specify some of the open() options.

The fancybox2 v2.1.5 docs for the API call open() says

$.fancybox.open( [group], [options] )

However the docs go into detail about [ group ] and say nothing about the format expected for the [ options ]

Furthermore the options seem to be ignored.

When I use

$.fancybox.open([{ href : ‘#popup_panel’ }], [ { ‘title’ : ‘Title Two’, ‘minWidth’ : 500 }] );

or

$.fancybox.open([{ href : ‘#popup_panel’ }], [ { title : ‘Title Two’, minWidth : 500 }] );

Fancybox seems to ignore the options… it opens, but there is no title and the minWidth is ignored.

Turns out, the fancybox documentation is wrong; options go inside the [group] apparently:

$.fancybox.open([{ href : ‘#popup_panel’, title : ‘Title Two’, minWidth : 500 }], [] );

Apple begins enforcing iDeal, demanding revenue split for deals discussed using iPhone

April 1st, 2014 – Cupertino, CA. “Our 10% share of any deal discussed using an iPhone has been clearly spelled out on the 837th screen of our license agreement since January 1st, as is our right to record all iPhone calls for purposes of enforcing this provision,” is the first sentence of the letter Apple has sent today to an estimated 31,778,000 iPhone users ranging from a Fortune 100 CEO in New York City to a hotdog stand owner in Peoria, Illinois. Most iPhone users have their phone linked to their Apple ID so their credit card was charged automatically via the Apple Store, unless the charge exceeded their credit card maximum. Other users received an invoice for their first-quarter revenue split. According to Apple, the iDeal charges ranged from $1.37 for a babysitter in Indiana to tens of millions of dollars for several Fortune 100 company CEOs and prominent Silicon Valley VCs, all of whom asked not to be named.

The Apple service was immediately dubbed “iVig” by surprised and angry consumers, many of whom said they had considered switching to a Blackberry device until they actually tried using one.

Apple CEO Tim Cook defended the service, citing not only that the iPhone user agreement explicitly opts-in all iPhone users “it’s right there in plain black and white if you just scroll down a little ways”, but adding “iDeal is a perfectly logical extension of our deathgrip on any and all transactions that occur within the Apple ecosystem. This should surprise no one.” Cook also noted that 23% of Apple’s iDeal receipts will go to the NSA “per terms of a joint venture wherein certain NSA tools are used to automate the process of tallying amounts owed from phone call recordings, giving our customers the seamless experience they’ve come to expect from Apple products.”

#lol#

April 1st, 2014 – Seattle, WA. In other news today, an estimated 37% of the world’s websites went dark at 12:01 this morning when Amazon suddenly withdrew from the web hosting business. In a tersely worded statement emailed to all Amazon Web Services customers, company CEO Jeff Bezos explained that “Since our acquisition of Zappos in 2009, it’s become increasingly apparent this web thing is actually more of a fad, whereas tangible products like shoes are here to stay.” The statement also noted that all (former) AWS customers would receive a free Amazon Prime membership for 3 months “to offset any inconvenience.”

#aprilfool#

Microsoft, please stop being such a whiny bitch

Not handling rejection well, Microsoft sends me 26
“I’ll give you one more chance not to break up with me”
emails in 12 hours

Dear Microsoft,

Look, we’ve all been dumped before. You just need to move on. It’s not about you. (Well, actually, it is about you, but that’s another story.)

As your Feb 8th email noted, I let the Office 365 trial expire. I’m just not that into you. It’s over. Just let it go.

And show some self respect.

Sending TWENTY SIX emails in a 12 HOUR period is unhealthy. Failing to provide an unsubscribe link in any of those emails is harassment.

I wish I could say let’s still be friends… but after the last 12 hours I’d like to not hear from you ever again.

Be well,

Pardner

Zerigo sets perfect example of how not to raise rates on prepaid plans

Zerigo announced this morning they are replacing their $39/year DNS Essentials plan with a $63/month plan, effective January 31, 2014.

That’s a month’s notice for a 1,800 % price increase.

But the worst part is, the annual plans are pre-paid, yet they will not grandfather existing annual plans through the end of the term… they are terminating pre-paid plans mid-way, and replacing them with a drastically-higher price plan.

Here’s the rub: due to infrastructure enhancements the new price actually is probably okay. But I would never remain with a provider who breaks their deal in that manner. They absolutely should have grandfathered existing plans through to completion.

UPDATE: painlessly migrated to Amazon Route53.

Getting S3Object.exists? to work correctly with IAM policies

When we updated our Rails 3.2 apps to each use their own IAM users and policies (instead of sharing a root S3 key/secret), we found that the aws-s3 (0.6.3) gem was causing S3Object.exists?() to always return true.

Although an updated aws-s3 gem may eventually fix the issue, the quick wrokaround was to modify the IAM policy to include both BUCKET and BUCKET/* (normally we need just the latter). Specifically:

{ "Version": "2012-10-17", 
"Statement": [ 
   { "Sid": "Stmt1234567890", 
    "Effect": "Allow", 
    "Action": [ "s3:*" ], 
    "Resource": 
         [ "arn:aws:s3:::SOMEBUCKET", 
          "arn:aws:s3:::SOMEBUCKET/*" ] 
}  ] }

Avoid “rate limit” errors when Geocoding in a Heroku app, using QuotaGuard add-on

We added some geocoding to one of our Heroku apps recently, and it seemed to be working fine during development and testing. However, once in production our automatic app health monitoring detected sporatic failures (the worst kind!) in the geocoding process. The logged showed the Google api would suddenly stop returning geocoding results due to rate limiting.

We were aware of Google’s limits on the geocode API, but our app uses geocoding infrequently so we were surprised to see the limits kick in.

In retrospect, the reason was obvious – Google meters usage by IP address, our app is hosted at Heroku, and the zillons of Heroku apps all share a very small number of IP addresses. So even if our usage was trivially small, other Heroku apps were chewing up the geocoding allotment for each Heroku IP.

Fortunately, the folks at www.quotaguard.com offer an add-on (currently in beta) to handle the situation… the ‘test’ plan provides a proxy service good for up to 2500 Google maps API requests/day, so your Heroku app’s requests to the geocoding api come from an IP supplied by Quotaguard (instead of the default Heoku IPs).

Enabling it was a snap:

  1. Add the quotaguard:test addon to your app

heroku addons:add quotaguard:PLAN (quotaguard:test for example)

This will add a QUOTAGUARD_URL setting to your Heroku environment, which you can see via heroku config

  1. If you’re using the geocoder gem, add this to config/initializers/geocoder.rb

Geocoder.configure( :http_proxy => ENV['QUOTAGUARD_URL'].gsub(/^http:\/\//, ''), :timeout => 5 )

Easiest workaround for Mac’s intermittent ‘disappearing cursor’ bug

If you’re one of the many dual-display Mac users plagued by Apple’s annoying disappearing cursor, the easiest way to get your cursor back is to drag a window from the working display to the no-cursor display, (If the display that is working correctly doesn’t have a window open, right-click the desktop and choose ‘get info’ which will open a small info window.)

You don’t have to drop the window onto the other desktop, simply drag it over, then drag it back. For some reason dragging something restores the cursor.

IF THAT DOESN’T WORK: The problme also seems to go away if you sleep the displays (keyboard shortcut Control + Shift + Eject) then hit a key to wake them back up.

The quick, easy, free way to send mail-merged email from a Mac

Suppose you’d like to use your Mac to send a couple hundred* customized emails once in a while, importing the recipient’s email + name + other data from a CSV file.

You’d think it would be a piece of cake.

Turns out, Apple Mail is worthless in this respect. Open Office has a built-in mail merge feature but it is poorly documented and horribly designed and works even worse. There is a Mac app called MailMergeApp, but it’s useless if you need to merge data from anything other than your Address Book.

Here’s how to do it using free software, and get it working in a few minutes:

1) Install the Thunderbird email client, at least for the purposes of sending merged-emails. (You don’t have to throw away your favorite email client.) We installed Thunderbird and configured it to use a dedicated outbound email address*.

2) In Thunderbird, open Tools > Addons and find and install the “Mail Merge” addon.

3) Follow the detailed step-by-step instructions on the Mail Merge webpage.

We particularly like the “send later” feature which creates each email and puts it in your Outbox, so you can make sure it all looks good before you do File > Send unsent messages

** Note, if you’re sending from a non-bulk-sender account (such as a typical Gmail or Godaddy email address), just keep in mind you probably have a maximum of 250-500 emails you can send per day. *

Managing multiple Heroku accounts with heroku-accounts plugin

This example assumes your pre-existing heroku account will be heroku.work and you are adding a new account heroku.personal.

It also describes how to move an app from one to the other, for example, if you have hit your 25-app max and are creating a new account and want to move some of your side projects and experimental apps out of your main account.

  1. You probably need to use the plugin to create BOTH your old and your new accounts, eg, if you had one to start with you can’t just add a new heroku.personal, you need to create heroku.work to replace your old one
  2. You’ll need to reassign your old apps to your heroku.work
  3. if you are moving an app, don’t assign the app to heroku.personal (using heroku accounts:set personal) until after you transfer the app using the heroku sharing commmand as described https://devcenter.heroku.com/articles/transferring-apps

So the steps you probably need are:

  1. Install the heroku-account plugin
  2. Go to heroku.com and create your new account (if you don’t have a second account already)
  3. run heroku accounts:add work --auto to create a new heroku.work account to replace your old default account (so use the same credentials you’ve been using all along). You ALSO need to upload your new key to heroku: heroku keys:add ~/.ssh/identity.heroku.work.pub
  4. run heroku accounts:add personal --auto to create a new heroku.personal account (eg use your new credentials for your new heroku account). You ALSO need to upload your new key to heroku: heroku keys:add ~/.ssh/identity.heroku.personal.pub
  5. For each app, cd to the project root then run heroku accounts:set work (all that does it setup git to use your heroku.work, which is (unin this example) the same heroku account you’ve been using all along, only now it’s called heroku.work.
  6. If you want to move an app from heroku.work to heroku.personal,
    (a) add the new heroku account as a collaborator with heroku sharing:add
    (b) in your local directory, switch the app to heroku.personal using heroku accounts:set personal
    (c) transfer** the app from the old account to the new account using heroku sharing:transfer then
    (d) remove the old email address collaborator (if you want to) using heroku sharing:remove

** Note the heroku link I provided says there are special requirements to move an app with any paid resources. Generally, remove the paid resoures, then add them back later, or have support do it.

Getting RSpec, Postgres, DatabaseCleaner to play nicely together

Did a quick benchmark last week to find the optimal way to configure Rspec on our projects that use Postgres and DatabaseCleaner

One of our test suites takes 3.5 minutes to run when we do NOT use DatabaseCleaner, the default rspec setup:

# spec_helper.rb
#config.use_transactional_examples = false 
#config.before(:suite) do 
# DatabaseCleaner.strategy = :transaction 
# DatabaseCleaner.clean_with(:truncation) 
#end 
#config.before(:each) do 
# DatabaseCleaner.start 
#end 
#config.after(:each) do 
# DatabaseCleaner.clean 
#end

When we enabled database cleaner (with default .strategy = :transaction), the test still took 3.5 minutes, but we got lots of warnings:**WARNING: there is already a transaction in progress
NOTICE: there is no transaction in progress
**

# spec_helper.rb
 #config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

However, when we changed the .strategy to :trunctation, it eliminated the warnings, but slowed the tests down to 8 minutes!# spec_helper.rb

#config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

The best results were to leave the strategy set to :transaction, but set config.use_transactional_examples = false. That yielded a runtime of about 3.5 minutes.

# spec_helper.rb
 config.use_transactional_examples = false 
config.before(:suite) do 
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation) 
end 
config.before(:each) do 
DatabaseCleaner.start 
end 
config.after(:each) do 
DatabaseCleaner.clean 
end

We used the following addition spec to verify that the database was being cleaned. (run this with –order default )

#dbclean_spec.rb

require "spec_helper" 
Refer.destroy_all 
describe Refer do 
it "has none to begin with" do 
  Refer.count.should == 0 
end 
it "has one after adding one" do 
Refer.create 
Refer.count.should == 1 
end 
it "has none after one was created in a previous example" do Refer.count.should == 0 
end 
end