a work on process

links for 2007-10-30

30 October 2007 (4:26 am)

By James Stewart
Filed under: Notes
Tagged:

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

Book Review: PHP Web 2.0 Mashup Projects

28 October 2007 (12:00 pm)

By James Stewart
Filed under: Book Reviews
Tagged: , , , , , , , ,

The market for books about mashups has become fairly crowded over the past few years but none have really enticed me as from a casual look most seem more interested in following the trend than offering solid information. Thankfully PHP Web 2.0 Mashup Projects manages to slide in a good number of practical programming tips as it works its way through a variety of services.

The book dedicates the majority of each chapter to more general concerns than just interfacing with the system in the chapter’s title. So Chapter 2—”Buy It On Amazon”—spends most of its time exploring XML-RPC and REST approaches and building tools to work with those different styles of interface. Similarly the next chapter spends most of its time introducing WSDL, XML Schema and SOAP before showing how they can be used with Microsoft Live Search.

In fact, that chapter may be one of the best introductions I’ve seen for developers who need to quickly grasp the basics of WSDL and SOAP, a topic that can far too easily get bogged down in complexity that isn’t needed for basic usage. With the WS-* stack quickly and for good reason going out of fashion hopefully most developers won’t have to spend much time with it, but a simple overview is still very handy.

I was intrigued to see the final chapter diving into use of RDF with the RAP toolkit. Like the SOAP section, this managed to boil the basics of RDF down very well and should help most moderately experienced PHP developers to get up to speed quickly.

Aside from a closing section on race conditions, not much time is given to handling interruptions in service from third-party services and in a book focussed on mashups that’s disappointing, particularly as the number of services, and so the range of fallback options, is increasing. Some of the examples are likely to fail if services time out and it would be good to spend some time on helping developers avoid that.

Reading the book as someone who has mostly left the PHP fold for pastures new was a reminder of how easy tools like hpricot make life for screen scrapers, but also that good structure can emerge in PHP code and that the SOAP tools are actually quite good for simple uses. The book is unlikely to appeal to those who don’t do much work with PHP, but if you’re a PHP developer and want to dive into mashups and web services for the first time, it’s worth a look.

Disclaimer: I was sent a copy of this book for review by the publisher, and offered another in return for a timely review. You can find it at packt, amazon US, amazon UK and all sorts of other places.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

On Tuesday evening I found myself at a google/demos event, How Has The Internet Changed British Democracy?. Unlike most discussions about the net and democracy I’ve attended, the panel here was very ‘establishment’, consisting of Demos Director Catherine Fieschi , Spectator Editor Matthew D’Ancona, Stephan Shakespeare, the founder of online polling agency YouGov, and BBC Political Editor Nick Robinson. Tom Watson MP was detained in the House of Commons, or he would have joined the panel.

Given the establishment panel it was refreshing to hear a general concensus that while there have been lots of indications of change, the real potential of the net has not yet been realised in British politics. Catherine Fieschi concluded her introductory statements noting that she doesn’t think the internet has changed democracy “yet in our societies, but I think it’s gone some of that way in others.”

A recurring theme, first clearly voiced by Spectator Editor was that we should be looking for a genuinely new form of politics for the internet age, and not simply how the net “facilitates and speeds up” the old forms. There was a general consensus that Gordon Brown’s recently announced “new politics” has (in the words of Catherine Fieschi) “a distinctly 20th century feel” but while many ideas were thrown around, what was naturally lacking was any description of what a 21st century version might look like.

Nick Robinson discussed in some detail how he came to start blogging, first in the form of an “election diary” some years back, and more recently again on the BBC News site. He pointed out that as TV reporter he didn’t get much feedback and that by providing a feedback mechanism the blog had helped his reporting. In particular he pointed to the resignation of former Liberal Democrat leader Charles Kennedy, when there was a sense among some members of the public that reporters had know of Kennedy’s drinking problem and were covering it up. Robinson claimed that he had been unaware of that sense, and that the blog made him aware of it and so able to address it directly.

Robinson was particularly concerned that in an age of on-demand television and increasing narrow-casting it is all too easy for viewers to “opt out” of the political news he believes is vitally important. He sees blogging and other new media as a way to engage a new audience. His eagerness to engage is impressive but I found myself wondering if a better way to handle a situation where people are only watching a narrow selection of news is to try to make sure that reporters work harder to convey the contexts of (and hence the interweaving between) their stories. He hinted towards this in suggestions that he wanted the BBC to make better use of amazon-style recommendation systems for news but I think it bears further development to help people dig deeper into the contexts their interests exist within.

Tom Steinberg of mySociety challenged the panel to discuss a “non-media” aspect of the political process they could see changing in the coming years as a result of the internet and while they shared a focus on the somewhat obvious element of direct accountability (as demonstrated to some extent by mySociety’s projects) the key interest seemed to be in the position for co-creation in the consultative and drafting process. We have tools to gather opinion and to collectively edit documents, can that be harnessed to change the way the government writes Green Papers?

Perhaps the strongest sense I took away was that government needs to wake up to the possibility and need for stronger feedback loops. At the mySociety Disruptive Technologies session earlier in the month Stef Magdalinksi led a discussion that spent quite some time on the need for campaign facilitators to provide feedback loops so that campaigners can see the impact of their actions and all involved can refine their work.

The same possibility exists for government who could be proactive in their responses to petitions especially, as Nick Robinson pointed out, those gathered through the Downing Street Petitions system. Government can use these systems to identify people with specific interests and to supply them with information, whether persuasive or simply educational, to deepen that conversation. Similarly people can be identified to receive alerts about consultations, to be invited to discussions, and so on. It may be possible for expertise and interest at the grassroots to more effectively bubble up into policy making.

It would be naive to think that major change that will happen quickly or withour pressure, but the possibilities are enormous and this session showed that there are people close to the policy making process who are thinking seriously about the possibilities.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

Taking readers step-by-step through the creation of the RailsCoders.net website, Practical Rails Social Networking Sites is a well paced guide to building web applications that tick many of the boxes of the moment.

The book starts with basics, giving simple instructions for installing Rails on a variety of platforms, and then steps through simple content management, adding users and groups, building a blogging engine, adding a discussion forum and photo gallery, integrating with Google Maps and Flickr, and deployment. Along the way the various aspects of rails’ testing framework are introduced as they’re used. The style isn’t test-driven, and it would have been nice to see that style introduced, but tests are written after each piece of functionality, demonstrating some of their use and importance.

Judicious use is made of plugins with a number of recommendations made throughout the book. restful_authentication is referred to, but its functionality is largely duplicated in the code. That’s probably a sensible move so early in the book as it’s important that developers understand what the code is doing even if they’re going to employ a plugin for the implementation. YM4R/GM is used to implement the Google Maps functionality and it’s good to see that getting some attention in print.

Readers who have already built a couple of rails apps may well find themselves skipping large chunks of content as a lot of the code will be familiar. As Stephen pointed out in his summary, it is a little curious that “The Apress Roadmap” suggests this as a more advanced title when it would probably work better for an engaged beginner than an experienced developer.

Of course, the great problem with publishing any rails title right now is that version 2.0 is just around the corner, and with its release we’ll see the end of built-in pagination and a few changes to the routes. As a consequence there are likely to be a number of readers who find that the examples in the book fail to run on the latest stable rails by the time they come to try them. Hopefully Apress will be able to offer a brief supplement with the book or online to help readers update the code for the new features.

Practical Rails Social Networking Sites is a solid introduction illustrating how simple it can be to build useful web applications with Ruby on Rails. I’d hesitate to recommend it to anyone with rails experience, but it will be high on my list of recommendations for beginners who are wanting to dive straight in.

Disclaimer: I was sent a copy of this book for review by the publisher. You can find it at apress, amazon US, amazon UK and all sorts of other places.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 

Since I wrote my first piece on extending a rails app to accept OpenID quite a few other tutorials and an official plugin have appeared to make that process easier. OpenID is quickly becoming quite mainstream, at least amongst developers, and that is very good news.

It’s becoming so mainstream in fact, that recently I’ve been asked to implement an OpenID server on top of an existing user database so that those users can have an easy single-sign-on option across a range of sites. Writing the server side piece is not quite so straightforward and there’s not much documentation yet. A few sample servers are available but the rails examples don’t run cleanly on the latest gems, so while I took some code from them it made most sense to start from scratch. Over the past couple of days I’ve hacked together something that works for me and even though it could still do with some polish a few notes follow. Please do use the comments to correct anything I may have gotten wrong or skipped over.

Firstly, a word on the process. The OpenID process works along the lines of:

  1. The client sends a request to the server to establish communication, shared keys, etc.
  2. Having established the keys, the client then redirects the end-user to the server to log in
  3. The server logs the end-user in however it wishes
  4. The server redirects the end-user back to the client with a query string indicating success or failure
  5. The client then confirms the success of the request with the server

I was starting from a very simple rails app that provided a Users resource and a Session resource. It’s really little more than a skeleton app with restful_authentication installed and configured. Users can log in and anyone can see a user’s page, and that’s all there is to it. I also had the ruby-openid gem installed and used a fair bit of code from the sample apps supplied with the gem.

Preparing The Existing Site

The first thing you’ll want to do is make sure that the HTML pages for your user resources have the correct headers. Chances are you will want users to be able to use their page (eg. http://yourapp.com/users/jystewart) as their OpenID but that won’t actually be where the login takes place, so you’ll want to put something like:

<link rel="openid.server" href="<%= session_url %>" />
</link><link rel="openid2.provider" href="<%= session_url %>" />
</link>

in the header block of your user page HTML. From that the OpenID client will know to redirect users to your sessions_url for authentication.

Preparing The Models

To my database that so far held the user details, I added four tables:

create_table :nonces do |t|
  t.string :nonce
  t.integer :created
  t.timestamps 
end
 
create_table :associations do |t|
  t.binary :server_url, :secret
  t.string :handle, :assoc_type
  t.integer :issued, :lifetime
  t.timestamps 
end
 
create_table :settings do |t|
  t.string :setting
  t.binary :value
  t.timestamps 
end
 
create_table :trusts do |t|
  t.integer :user_id
  t.string :trust_root
  t.timestamps 
end

The first three hold the various details we need for the negotiations with the client, and the fourth stores the details of any sites a given user has said they want to always trust so that we don’t need to confirm those details every time.

We also need an implementation of the OpenID::Store class for the OpenID library we’re using. I simply copied the one from the sample rails app distributed with the gem. With the models and that interface in place we can move on to managing the requests.

Distinguishing OpenID Requests

I decided to use a Mime::Type alias to distinguish between requests made directly in my app and those coming through OpenID. To do that I added:

Mime::Type.register_alias "text/html", :openid

in RAILS_ROOT/config/initializers/mime_types.rb and added the following code in my controllers:

before_filter :check_for_openid_request
 
private
  def openid_server # :nodoc:
    @openid_server ||= OpenID::Server::Server.new(ActiveRecordOpenIDStore.new)
  end
 
  def openid_request
    @openid_request ||= openid_server.decode_request(
      openid_params.delete_if{ |key, val|
        key == 'openid.session_type' && val == ''})
  end
 
  def check_for_openid_request
    @openid_params = session[:openid_params] if session[:openid_params]
 
    if openid_request.is_a?(OpenID::Server::CheckIDRequest)
      session[:openid_params] = @openid_params
      request.format = :openid 
    end
  end

Because there are going to be several steps to our process during which we want to be able to hang on to the OpenID request details, I chose to store them in the session

Handling The Requests

Having defined our Mime::Type alias, we can now use openid as a type in respond_to blocks. The first step then is to change our SessionsController#create action from:

def create
  self.current_user = User.authenticate(params[:login], params[:password])
  if logged_in?
    if params[:remember_me] == "1"
      self.current_user.remember_me
      cookies[:auth_token] = { 
        :value => self.current_user.remember_token, 
        :expires => self.current_user.remember_token_expires_at }
    end
 
    flash[:notice] = "Logged in successfully"
    redirect_back_or_default(user_path(current_user))
  else
    render :action => 'new'
  end
end

to:

def create
  self.current_user = User.authenticate(params[:login], params[:password])
  if logged_in?
    if params[:remember_me] == "1"
      self.current_user.remember_me
      cookies[:auth_token] = { 
        :value => self.current_user.remember_token, 
        :expires => self.current_user.remember_token_expires_at }
    end
 
    respond_to do |wants|
      wants.html { 
        flash[:notice] = "Logged in successfully"
        redirect_back_or_default(user_path(current_user))
      }
      wants.openid { 
        if @trust = current_user.trusts.find_by_trust_root(openid_params['openid.trust_root'])
          successful_openid_login 
        else
          redirect_to new_trust_url
        end
      }
    end
  else
    render :action => 'new'
  end
end

This checks for a successful login and if it’s an OpenID request then checks to see if we already trust that site. If we do, we call the ’successful_openid_login’ method and if not, we redirect the user to ask if they want to trust the client site. The successful_openid_login method looks like:

def successful_openid_login
  session[:openid_params] = nil
  @resp = openid_request.answer(true)
  @resp.add_field(nil, 'is_valid', 'true')
  add_sreg
  render_openid_response
end
 
def render_openid_response
  response.headers['Content-Type'] = 'charset=utf-8'
  @resp = openid_server.encode_response(@resp)
 
  case @resp.code
    when OpenID::Server::HTTP_OK
      render :text => @resp.body, :status => 200
    when OpenID::Server::HTTP_REDIRECT
      redirect_to @resp.redirect_url
    else
      render :text => @resp.body, :status => 400
  end   
end

And is almost entirely taken from the code supplied with the gem. I ran into some trouble with the ‘is_valid’ field not being added to the responses but being needed by my clients, so added the line

@resp.add_field(nil, 'is_valid', 'true')

The TrustsController implementation is quite straightforward and I’ll not go into details here, but will include it in the zip file you can download at the end of this entry.

This code will handle most of the process, but we have one remaining query to handle, and that is the final check_authentication request that is used to confirm everything fell into place. The actual request will come as a POST to your /session path so you will want to be ready to handle it there. I decided to implement a before_filter to intercept it and handle it separately rather than clutter my create method still further:

before_filter :handle_openid_check_auth_request
 
def handle_openid_check_auth_request
  if openid_params['openid.mode'] == "check_authentication"
    signatory = OpenID::Server::Signatory.new(ActiveRecordOpenIDStore.new)
    @resp = openid_request.answer(signatory)
    @resp.add_field(nil, 'is_valid', 'true')
    render_openid_response
  end
end

Once I had the code working acceptably I pulled it out into a separate module in the ‘lib’ folder. As the code matures it would probably be a good candidate for a rails plugin, but I’m not going to have time to put that together on my own for a while. If anyone wants to collaborate on that, get in touch in the comments (or by email) and maybe we can make it happen.

All the code above along with various other utility methods can be found in this zip file.

Recommend this post:

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

 
Next Page »