Skip to content

Reflections on Pycon 2013

By now, anybody interested in web development is likely to have heard what happened at Pycon. Posts on the topic have consistently been at the top of Hacker News for the last 48 hours however 2 posts that appeared overnight have really crystallised my thoughts on the matter. Before going into that, I’m going to repeat what I said in one of the discussions over on HN:

This story is an embarrassment for everyone involved except perhaps the 2 guys who started the whole thing.

* Adria Richards had a number of options starting with explaining to them that the jokes made her feel uncomfortable to reporting them to staff. Instead she went for the nuclear option of public shaming.
* Sendgrid will only appear to have done this in response to their site being subject to DDOS.
* Playhaven have overreacted in dismissing one of the guys (although their blog post suggests there might have been more behind it).

The guys involved apologised at the time and have done so publicly. I can’t help but feel that if Adria had apologised for her course of conduct at the first opportunity, this thing would have blown over.

Instead you have another story about misogyny in the industry that has run for over 24 hours with nobody looking good at the end of it and everybody suffering.

I should have added that the Pycon organisers came out of this without embarrassment too. They had an anti-harassment policy and enforced it properly.

The two posts I refer to above were these: What really happened at Pycon 2013 and Adria Richards, PyCon, and How We All Lost.

Taking the second post first. Amanda expresses in a much more eloquent fashion what it is that I tried to say on HN. In terms of possible reactions to the jokes, there is a scale of say 1-10. 1: sit there and do nothing, 4: confront them directly, 6: report them to the organisers etc. Instead of taking any of these options, Adria went straight for 10. It’s clear from Amanda’s post that this is not the first time Adria has done something like this. Rather than confront issues in what I would consider to be a mature, adult manner, she tends to make it a “thing” and in doing so, makes it about her. As I said in my comment, the community as a whole suffers because of things like this.

Which brings me to the first post. Adria’s actions have made Pycon about her and in doing so distracted from the brilliant work put into organising Pycon and the actual substantive events that took place. For this, I have great sympathy for the organisers whose work has been greatly overshadowed.

I can’t help but feel that given the very genuine apology made by one of the individuals involved, direct confrontation at the time (level 4 on my scale above) would have knocked the issue on the head. Instead, we’re left with 2 people being fired; Sendgrid being subject to a DDOS attack; Adria being subjected to vitriol on Twitter and a community left reflecting not on the good it does but on another drama.

Ember.js and me

On reading Hacker News yesterday morning, I was interested to see a link to this discussion about ember.js. The frustrations in that post mirrored my own frustrations in trying to get to grips with Ember.

One of the big problems in the Ember Guides is that they tie the use of Ember very closely to using ember-data, something which they themselves admit is not production ready. Not wanting to use something that is prone to breaking changes, I decided to try to use jQuery’s AJAX functionality and it is at this point that things fell apart.

The Routing guide describes a route handler thus:

The route handler is responsible for converting the URL into a model object, telling a controller to represent that model, then rendering a template bound to that controller.

And the corresponding code (using ember-data) does exactly that:

App.PostsRoute = Ember.Route.extend({
  model: function() {
    return App.Post.find();
  }
});

In my head, if using jQuery, I should be able to replace the line return App.Post.find() with something akin to:

App.PostsRoute = Ember.Route.extend({
  model: function() {
    $.ajax({
      url:'/posts',
      dataType:'json',
      success:function(response) {
        return response.posts
      }
    })
  }
});

If you do this, it won’t work.

Linked in the original discussion about Ember was this Ember Quick Start Guide, which uses jQuery. In the section on models, it looks like I need to reopen the relevant class, create an Ember array to hold the posts and then return that array. But, in this tutorial, the AJAX call is in the model, not the route. Now, I’m confused.

Unfortunately, for Ember, a number of tutorials appear to have been written before what I understand to have been major changes to the router and these tutorials appear very high in the search results.

As it is, I gave up using Ember and have resorted to using Handlebars templates but without a front-end framework and I got further in 2 hours yesterday than I had in about 6 hours of using Ember.

The comment from Yehuda Katz in the HN discussion makes it clear that the core team knows about these problems but until they are fixed, I expect that people will continue to move on and use something else.

In which BT live up to stereotype

I’m moving house on the 28th March. Everytime I have moved, there has been an almost seamless transfer of my broadband service. Sure, it might be down for a few hours, a day at most, but not so much that I’ve noticed in the drama of moving. Unfortunately, facilitating a seamless transfer of my BT Infinity broadband seems impossible.

I notified BT that I was moving and had an installation date of the 28th March for my phone line and broadband. Note that the installation of the phone line doesn’t require a visit. The actual line is already in the property, I just needed to transfer my number. About a week after placing the move order, I received the following email. It is so badly written, I questioned for a second if it was genuine:

Dear Mr FISHER, this is a message from BT Retail.
We have tried to contact you today but unfortunately been unable to reach you.
We were calling to advise that your phone line will be connected at your new address on 28/03/2013 without an engineer visit required, however we need to reissue the infinity broadband once your telephone line is working so we will contact you on Friday 29th March with a new appointment Date.
We apologise for the inconvenience caused.
Many Thanks
BT Retail.

I called BT who told me that my broadband appointment had been cancelled because the system would not let them book it until the line was ready. I could only book my broadband appointment after 28th March when the phone line was installed. When I asked about access to the internet during this time, I was told to use the local BT hotspot. Oh, except customer services couldn’t tell me if there was one in my area.

Astonished at the inability of BT’s system to book a broadband installation where they are themselves installing the line on the previous day, I thought I’d send a complaint to customer services. The response was thus (emphasis added):

Hello Mr Fisher,

Thanks for getting in touch.
I am really sorry to hear about the problems with your current order for services at your new address.
I am very sorry for the recent problems you have experienced with us. At BT, we strive to deliver and maintain the highest possible standards of customer service. The service you have received over the past couple of weeks has fallen short of this. I really do sympathise with your comments and I can understand the frustration which you have expressed. Please accept my apologies for these difficulties and for the inconvenience this has caused.

We some times unfortunately fail in our agreed dates for provision due to technical issues or order failures; we of course never want to let our customers down. All orders are however subject to survey which does mean some times delays happen that our out of our control. We hope that this never happens but it sometimes unfortunately does.

We don’t like when things go wrong like this and our customers are let down. We will of course be feeding this case back to Open reach that now take care of our and all other telecommunication companies engineering works. We have been let down due to the work carried out by the engineers which in turn means that we unfortunately fail in our agreement with you. All orders however are subject to survey and do from time to time go wrong. I am sorry you have to experience this.
Unfortunately what has happened is the Broadband part of the order failed. When this happens we need the line to be activated and then the Broadband re- ordered.
I can assure you that this order is now being case managed by our specialist orders team and they will be in contact with you to arrange the infinity appointment when the line is activated.
I appreciate this reply doesn’t resolve this issue for you and I am sorry that I have been unable to do anything for you. For an update on the progress of your order you can call the dedicated My Order team on 0800 121 8125.
You may receive an e mail survey; some of this is about how I helped you, I’d really appreciate it if you could take the time to fill it in.

If you’ve any other questions go to http://www.bt.com/help. If you can’t find the answer there, we’ve included lots of ways to get in touch.

Best Wishes,

Mxxxxxx Dxxxxxx
BT Digital Care

To be honest, I’m not sure they even understood the complaint.

If I thought it would be any easier to have another provider install fibre-to-the-cabinet, I’d terminate my contract with BT on the basis they are failing to provide a paid for service. As it stands, I think I will be stuck without broadband for about a week when I move.

Apache virtual hosts on Mountain Lion

I recently upgraded my Macbook to Mountain Lion from Snow Leopard. The reason was to be able to use iBooks Author.

When I tried to do a bit of development on Leavetrack last night, I had the problem that my development environment was unresponsive. I use Phusion Passenger in my production and development environments with various sites set up as virtual hosts. My initial Google research led me to a number of posts about Apache being disabled by default in Mountain Lion.

I made sure that Apache was running and reinstalled Passenger but still my development site was unresponsive.

Some further Googling led me to this post on ServerFault. It appears that in Lion and Mountain Lion, Safari defaults to IPv6 lookups first and then IPv4 lookups. As my virtual host blocks were using the *:80 format, it was hanging on the IPv6 lookup.

A combination of the top two answers on that post resolved the issue for me.

 

What is the point of Facebook anymore?

I opened up Facebook on my iPhone and the top 10 posts in my News Feed were, in order:

I have c. 100 friends on Facebook and refuse to believe that they have all given up on posting, but maybe they have. Particularly if they are having the same experience that I am.

It must be the case that the market currently occupied by Facebook is ripe for opportunity. I think the appeal of these global forms of communication will diminish over time as people look for more meaningful relationships online. And Facebook is a global form of communication for many people. Not global in the sense of Twitter but global in that only the savvy segregate their friends into lists and post certain types of content to certain lists.

It certainly appears that Facebook is sacrificing the reasons that people joined the site for exposure to promoted posts and advertisers.

Is it possible to create something that appeals to everyone for every use case? I don’t think so. Is it time to target niches more effectively? How do you make people reach out and connect to friends they’ve not spoken to or seen in a long time? How do you make colleagues freely share information with each other?

Even if a solution to these questions were identified, the more pressing question of how to achieve critical mass becomes prevalent. Nobody wants to use something if they’re the only one using it. People use Facebook because their friends do, even if they have to scroll through 5 posts to find the first piece of meaningful content.

Some months ago, I gave consideration to building an application that would allow me to share photos of my newborn son with family. Most of my family don’t have Facebook accounts but have email addresses. And I don’t want to put photos of him for the world to see on Facebook anyway. And there is the risk that those photos get buried in a stream of promoted posts for online degrees. The application would in effect be a private photo-sharing application.

This is the type of meaningful communication that should exist but doesn’t. It should be open and easy to use and not require setting up a Facebook account. I honestly believe that people are looking for that deep connection with others.

Strong Parameters in Rails 4

On the 4 March 2012, Egor Homakov took advantage of a mass assignment vulnerability to add his public key to the Rails repository, thereby giving himself commit access to Rails. It appears he carried out the exploit when the issue he raised in Github was closed as a “won’t fix”.

To understand the issue, you need to understand how Rails makes it easy to interact with the database. If you have a form to create a model, Rails will pass a hash of parameters on the form being submitted. If you check your logs when submitting a form, you will see something like this for say a User model:

:user => {:name => "Robin Fisher", :email => "robinjfisher@gmail.com", :hometown => "London"}

In the controller, you can access this hash to create or update your user:

def create
  @user = User.create(params[:user])
end

At the time, Rails had a permissive design in that unless defined otherwise, any attributes on our User model could be set through mass assignment. If you had an admin attribute on your User model, a hacker could manipulate the form or use the command line to update that attribute by setting the admin attribute to true.

Rails did have methods to prevent this. A developer could use the attr_accessible method to whitelist attributes that could be updated via mass assignment or the attr_protected method to blacklist attributes. Homakov felt however that leaving this to the developer was the wrong choice and to prove his point, made a couple of educated guesses as to Github’s database design to exploit the vulnerability and add his public key to the Rails repository which gave him commit access.

Following this, Rails was updated so that it was secure by default. Unless an attribute was listed in an attr_accessible method, that attribute could not be updated via mass assignment. And so it was.

There had been much discussion as to whether this control sat better in a Controller or Model. For Rails, the decision was made to put this control into the Controller. When Rails 4 is released, it will ship with the strong_parameters gem built into the core.

It has of course always been possible to define this protection in the controller. It is possible to use the slice extension to Ruby’s Hash class to return only the parameters you want:

def create
  @user = User.create(user_params)
end

private

def user_params
  params[:user].slice(:name, :email, :hometown)
end

This was not without risks.

The strong_parameters gem introduction states:

With this plugin Action Controller parameters are forbidden to be used in Active Model mass assignments until they have been whitelisted. This means you’ll have to make a conscious choice about which attributes to allow for mass updating and thus prevent accidentally exposing that which shouldn’t be exposed.

In addition, parameters can be marked as required and flow through a predefined raise/rescue flow to end up as a 400 Bad Request with no effort.

In our controller, we would now define our create action as follows:

def create
  User.create(user_params)
end

private

def user_params
  params.require(:user).permit(:name, :email, :hometown)
end

This will create our user provided that:

  1. The parameters hash contains a user key; and
  2. The hash does not contain any keys other than those permitted

It’s possible to start preparing your application for Rails 4 by incorporating this gem into your Rails 3 application. Follow the instructions for installing the gem and then follow the example above to set your permitted attributes at a controller level.

When Rails 4 is released, you will simply need to remove the gem from your Gemfile.

If you enjoyed this post, you should sign up to be notified when my book, Real World Development with Ruby on Rails, is released in May 2013. The book and full source code to the application we develop in it will be just $39 with added value packages also available.

Using localtunnel with Apache Virtual Hosts and SSL

As part of the ongoing development of Leavetrack, the easiest way to track employees’ holiday and other absences, I’ve been working on integrating Twilio so that users can receive notifications via text message and approve requests via text message.

Part of this requires routing incoming text messages to my local development environment. There are a number of services that can expose localhost to the world but I chose localtunnel, which an engineer at Twilio created.

A lot of the example cases are based on running Rails default server which operates on port 3000. For my purposes however I have a named virtual host (leavetrack.local) which makes it easy to work with SSL in development and subdomains, both of which are key for my application. In order to get localtunnel to work in my environment, I did the following:

1. Configured httpd.conf to serve Leavetrack as the DocumentRoot:

DocumentRoot "/Users/robinjfisher/Code/leavetrack/public"

2. Defined a virtual host in my httpd-vhosts.conf file listening on port 80. To date my application worked entirely under SSL using mod_rewrite. However, this rewrite was causing the parameters to be dropped so I added a rewrite condition to cancel the redirect where the URL is that defined for incoming messages:


  ServerName leavetrack.local
  ServerAlias *.leavetrack.local
  RackEnv development
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteCond %{REQUEST_URI} !^/sms$
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
  RewriteLogLevel 2
  RewriteLog "/var/log/apache2/rewrite.log"

3. In my Rails application, I exposed a route at /sms which pointed to the create action of the Messages Controller. In my Twilio dashboard, I then pointed the SMS Request URL to the localtunnel address with /sms appended.

Now, when I send a text message to my Twilio number, it is routed to my local machine at which the create action in my Messages Controller parses the content and creates the corresponding message in the database.

 

Things I did whilst away

Aside from my last  post, it’s been a long time since I posted anything here. I stopped because I fancied doing a redesign and then got caught up in all manner of things. In an effort to restart, I’ve moved the blog from my own server to WordPress.com. Whilst redirecting domain name I realised I’ve had this domain registered since 2006. A long time in internet years.

Whilst I’ve been away, I did the following things:

As briefly mentioned in my previous post, I’m writing a Ruby on Rails book aimed at intermediate developers that will go through the creation of a real life application. I’ll have a launch page up soon with more details.

Counting words in documents using Ruby

For a little book I’m working on, I have a number of files written in Markdown each in separate directories based on their chapter number. I needed a quick and dirty way to count the number of words in a number of files spanning multiple directories.  After a little trial and error, here is the solution:

root = Dir.getwd.to_s
directories = Dir.entries(".").reject!{|d| !["1","2","3","4","5","6","7","8","9"].include?(d.slice(0))}
count = 0
directories.each do |dir|
  Dir.foreach(dir) do |file|
    Dir.chdir(dir)
    chapter = File.open(file)
    if File.file?(chapter)
      File.open(file,"r").each do |line|
        count += line.split.length
      end
    end
    Dir.chdir(root)
  end
end
puts count

I saved this in a file called word_count.rb in the root of the directory where all the book-related files/folders are stored.

If you enjoyed this post, you should sign up to be notified when my book, Real World Development with Ruby on Rails, is released in May 2013. The book and full source code to the application we develop in it will be just $39 with added value packages also available.

Metrics

Inspired by Ryan Carson’s post on tracking campaign effectiveness, I’ve open-sourced the beginnings of a starter app called Metrics.

Follow

Get every new post delivered to your Inbox.

Join 171 other followers