A guy goes in to consult for a company and runs across a bug. He raises the issue and the boss says “Oh boy – another ‘Bob bug’ – Bob created a lot of bugs.” (Bob has moved on by now). After the guy was there for a while he comes to realise that Bob wrote most of the code while the rest of the staff wrote very little. The perception that Bob created a lot of bugs was technically correct, but an analysis of bugs per line of code written show that Bob actually made fewer mistakes than his co-workers, but since he generated the majority of the app, he had the majority of the bugs.
Read MoreI’m generating PDFs with PDFkit/wkhtmltopdf on a current project. While the output is fine in the browser, £ (pound) signs in the generated PDF were showing up incorrectly as:
£
The fix was relatively easy as PDFs have their own view layout, so all I had to do was add an extra meta tag to the head:
Read More<meta http-equiv="content-type" content="text/html; charset=utf-8" />
My current project www.viewshound.com requires different users to have different scopes for their Facebook authentication. Warden supports dynamic providers out of the box. To get it working with Devise was pretty easy, just a couple of minor changes were needed especially to support Facebook.
First up was creating the new route. As I’m using a controller called Omniauth and not Session, the :to attribute is different. The other thing to note is I’m matching /users/auth/facebook/setup, not /auth/facebook/setup like in the Warden documentation.
routes.rb
devise_for :users,
:controllers => { :omniauth_callbacks => "omniauth" },
:skip => [:sessions] do
match '/users/auth/facebook/setup', :to => 'omniauth#setup'
end
Next we create the new setup action for Warden to call. The docs use consumer_key and consumer_secret, but facebook expects client_id and client_secret, so be sure to use those instead. This is where I make changes to the scope based on the current user if they are signed in or not. So a user can re-authenticate with Facebook to get more permissions for their account if they wish.
omniauth_controller.rb
class OmniauthController < Devise::OmniauthCallbacksController
def setup
request.env['omniauth.strategy'].client_id =
{your_facebook_id_here}
request.env['omniauth.strategy'].client_secret =
{your_facebook_secret_here}
request.env['omniauth.strategy'].options =
{:scope => your_facebook_scope_here}
render :text => "Setup complete.", :status => 404
end
end
Finally change the devise.rb initializer to support the new setup.
devise.rb
config.omniauth :facebook, nil, nil, :setup => true
Restart your application and you should be good to go.
Read MoreI just realised that my NERDTree directory colour wasn’t inline with my Vim theme, and I couldn’t help but be bugged by it. Seems it’s a simple change. To change colour you need to use the treeDir highlight group.
:hi treeDir guifg=#96CBFE guibg=#00ff00
To keep it synced with the ir_black theme I use, I just added the following to my colour scheme file.
Read Morehi link treeDir Keyword
Recently I’ve been coding some iPhone and iPad apps with multiple targets, all sharing the same codebase. Previously I had been using Preprocessor Macros to get the job done, but that soon turns messy and hard to maintain. I’ve since moved to just storing target specific values in each apps related plist file. Retrieving a value is as simple as:
Read MoreNSDictionary* infoDict = [[NSBundle mainBundle] infoDictionary];
NSString *someString = [infoDict objectForKey:@"SomeKey"];
Installing the intermediate certificates on our server gave me the following error while trying to start up nginx again:
(SSL: error:0906D066:PEM routines:PEM_read_bio:bad end line)
The end of the file looked fine, but the problem was half way through it. Somehow the concatenation had joined two lines together:
-----END CERTIFICATE----------BEGIN CERTIFICATE-----
This just needed a line break to fix:
Read More-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
A current requirement is that assets uploaded to Amazon S3 must be accessed via SSL and use an expiring URL. Using an expiring url with Paperclip is extremely easy.
my_model.image.expiring_url(5)
The problem is expiring_url doesn’t let you choose a style and doesn’t use https, which breaks our SSL site. To add the behaviour was an easy “hack”. I added the file /config/initializers/paperclip.rb with the following code:
module Paperclip
module Storage
module S3
def expiring_url(style = default_style, time = 3600)
AWS::S3::S3Object.url_for(path(style),
bucket_name,
:expires_in => time,
:use_ssl => true)
end
end
end
end
Now calling my expiring image URL with a style and over https is just:
Read Moremy_model.image.expiring_url(:original, 5)
![]()
First let me state how much I dislike developing for the Facebook platform. It’s just one constant headache. Things are always changing and breaking things. Anyways, I’ve been banging my head against the wall all day trying to get some FBJS running on a canvas application that’s embedded on a Fan Page tab. No matter what I did, I kept getting the error:
'FBML' [undefined] is not an object.
Even using Facebook’s own FBJS examples left my tab in a hung state, with the spinner just continuing forever. After hours of playing around, the problem is that I’m trying to use Javascript one page deep into the application (The landing page itself has no FBJS). Once I added an opening and closing script tag to the landing page, my FBJS woes vanished.
Read More<script>
<!--
//-->
</script>
Recently the discussion of code quality has come up with a couple of different people. With the main question:
“If the app does what it’s supposed to do, why does code quality matter?”
In one instance an application that was bringing in over a £1m in revenues a month had one of the worst code bases a friend had ever seen. And I totally agree that there is no correlation between code quality and the earnings/growth potential of an application. Then a few days ago I was reading the brilliant Zed Shaw article “Products For People Who Make Products For People” which completely crystalised why code quality is important:
“… the frontend product is what brings your revenue stream in, but your backend operations quality is what keeps your costs down as you grow. If your backend costs get out of control because of technical debt then you won’t make a profit, or someone who can keep them down will just copy you and wipe you out with less.”
Perfect! That’s it exactly. Code quality matters as that’s what allows you to grow the system beyond your v1. If you never plan/or want to get past v1, then perhaps you can get away with being a lot more lieniet in your “quality”. I know that’s what I do, if it’s a quick app then normally I have only the most basic of tests and cut corners where I wouldn’t normally. Maybe in a sense, code quality is a reflection of technical debt. The lower the quality, the higher the debt and sooner or later you’re going to have to pay that back (Unless you’re fortunate enough to close up shop before that time comes). I’ve worked on projects where the technical debt is so high that you’re paralysed and just can’t do anything. Simple changes become huge problems as you’ve been painted into a corner, and the fear of breaking something is so huge that new feature requests are shied away from.
If you want/expect to be able to grow your business then keep the bar high. Code quality matters a hell of a lot.
Read MoreTo get webby using HAML/SASS’ SCSS rendering engine I added the following to my Sitefile. No doubt there’s a cleaner and quicker way of getting it working, but this works.
Read MoreWebby::Filters.register :scss do |input, cursor|
opts = ::Webby.site.sass_options.merge(cursor.page.sass_options || {})
opts = ::Webby.site.sass_options.merge(:syntax => :scss)
opts = opts.symbolize_keys
opts.merge!(:filename => cursor.page.destination)
opts[:style] = opts[:style].to_sym if opts.include? :style
Sass::Engine.new(input, opts).render
end