h1

Jumping on the Rails Pt.4 – Spec’n our form

July 11, 2009

Well carrying on from the previous post, we’ll focus on some actual functionality in this post & start on creating the functionality for users to create new projects. As always we’ll start off with our feature:


	Feature: As a registered user I must be able to create projects
	  In order to create a new project I must be logged in
	  As a registered user
	  I want I want to be able to create new projects

		Scenario: A registered user must be able to create projects
		  Given an activated user named 'reggie'
		  When I click new project
			And fill in the new project form
		  Then I should get confirmation of the successful creation

As we’re using restful-authentication’s stories we can save our selves a step ;) , as well as having knowing that the user will be logged in.

This leads us to our next step, we need to make sure that we can click the new project link, so that we can actually create our new project, so we take our snippet & modify it to look like the example below.


	When /^I click new project$/ do
	  visit "/projects/new"
	end

Now that we have our first failing test,it’s time to jump down into our view specs, we’ll start with the view first. So we will need to create the following file:

/PROJECT/spec/view/project/index.html.erb_spec.rb

Now there are a few things here that we not specified in the our story:

  • a guest user should not see the new projects link
  • only registered users can see the new projects link

now for those of you that have never created a spec before, we’ll start off slowly.

All specs have the following template


	require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')

	describe "/welcome/index.html.erb" do
	end

Now the first line brings in our specs helper which basically sets up rspec for us, the next significant line is:


	describe "welcome/index.html.erb" do
	end

Within this we describe the things we are testing, in this case the index view of our welcome page.

With the basics out of the way, we’ll start by setting up the first test.


   it "should have a sign up link" do
     response.should have_selector("a", :content => "Sign up")
   end

This test should pass straight away seeing as we haven’t added the link yet. Next we’ll do a little refactoring as our specs are now defining different types of user actions, our code now look like this:


	require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')

	describe "/welcome/index" do
	  context "viewing as a unregistered user" do
	    before(:each) do
	      render
	    end
	    it "should have a sign up link" do
	      response.should have_selector("a", :content => "Sign up")
	    end

	    it "should not have a new project link" do
	      response.should_not have_selector("a", :content => "New Project")
	    end
	  end

	  context "viewing as a registered user" do
	  end
	end

Now we’re wrapped our specs in context blocks, i’ve done this basically to help visually and mentally tell the difference between the two blocks of test, the first context block focusses on users that are not registered, whilst the second deals with specs concentrating on users viewing the index page as a registered user.

Now that the refactoring is out of the way lets deal with our next spec.


	context "viewing as a registered user" do
    it "should be able to see the new project link" do
      response.should have_selector("a", :content => "New Project")
    end
  end

Our tests will now fail so now its time to get our test to pass.


	<a href="/project">New Project</a>

I know, we can make this a lot more Railsy but let concerntratet on the matter at hand, we still have a failing test.


	'/welcome/index should not have a new project link' FAILED
	expected following output to omit a New Project:

Our initially passing test is now failing, lets get that to pass and move along.


	context "viewing as a registered user" do
    before(:each) do
      template.stub!(:current_user).and_return mock_model(User)
    end
    it "should be able to see the new project link" do
      response.should have_selector("a", :content => "New Project")
    end
  end

Our spec is passing but out definition is still failing, thought we are making some progress, we are greated by our next friendly error.


	When I click new project                                  # features/step_definitions/registered_users_step.rb:2
    No route matches "/projects/new" with {:method=>:get} (ActionController::RoutingError)

Well we don’t have a route for our project, so lets get that setup, we add the following to

PROJECT/config/routes.rb

:


	map.resource :projects

With our route now setup, we have another error:


	When I click new project                                  # features/step_definitions/registered_users_step.rb:2
	      uninitialized constant ProjectsController (NameError)

That seems simple enough, we just need to create a controller for our projects, creating

PROJECT/app/controllers/projects_controller.rb

:


	class ProjectsController < ApplicationController

	end

Our tests run again but wait? yet another error:


	When I click new project                                  # features/step_definitions/registered_users_step.rb:2
	      No action responded to new. Actions: authorized?, current_user, and logged_in? (ActionController::UnknownAction)

Oh yeah, we need to create the new method block:


	class ProjectsController < ApplicationController
	  def new

	  end
	end

Now we run the tests again, next our tests tell us to create a view for our project.


	When I click new project                                  # features/step_definitions/registered_users_step.rb:2
	      Missing template projects/new.erb in view path app/views (ActionView::MissingTemplate)

So lets create the template

PROJECT/views/projects/new.html.erb

. Our tests are now passing and we can move on to the next step.

Before we jump in, we take a step back and think about what type of information we want to store in our project.

Well we certainly want a project title & we could do with a small description of what the project is about. It would also be nice for the project to have aims.

Ok, now that we have a rough idea of what data we want to store in our project, it’s time to setup our definition.


	When /^fill in the new project form$/ do
	  fill_in 'project_title', :with => 'new project'
	  fill_in 'project_description', :with => 'This project will help us manage stuff'
	  fill_in 'project_aim', :with => 'To provide a service'
	  submit_form 'new_project'
	end

So now we have our first error:


	Could not find field: "projects_title" (Webrat::NotFoundError)

We need to create a field with the id projects_title. So lets dip down into our view specs to step out this functionality.

We create

PROJECT/specs/views/projects/new.html.erb_spec.rb

first and the add the following code:


	require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')

	describe "/projects/new.html.erb" do

	  it "should have a form" do
			@project = mock_model(Project)
	    assigns[:project] = @project
	    render
	    response.should have_tag("form[action=/project][method=post]") do
	      with_tag('input#project_title[name=?]', "project[title]")
	      with_tag('textarea#project_description[name=?]', "project[description]")
	      with_tag('textarea#project_aim[name=?]', "project[aim]")
	    end
	  end
	end

Now this is a little involved but we’re basically looking for a form which contains a text field and two textarea’s, which will store our title, description & project aim. I also mocked out the project model from the jump, though it’s a bit naughty to do this all the time, I knew I was going to need a Project model here, so I just mocked it out.

We now get the following error:


	'/projects/new.html.erb should have a form' FAILED
	Expected at least 1 element matching "form[action='/project'][method='post']", found 0.
	<false> is not true.

This is basically telling us need to now create our form. So we create our new view

PROJECT/app/views/projects/new.html.rb

and add the following code:


	<% form_for @project do |f| -%>

	<% end -%>

Next we get the following error:


	NameError in '/projects/new.html.erb should have a form'
	uninitialized constant Project

So this error tells us we need a new project to pass the to the form, so we’ll add it to make our controller look like below


	class ProjectsController < ApplicationController
	  def new
	    @project = Project.new
	  end
	end

We’ll get a similar error if we don’t create our actual model, so lets quickly do that know:


	class Project < ActiveRecord::Base
	end

And we’ll need to create our migration table also.


	class CreateProject < ActiveRecord::Migration
	  def self.up
	    create_table "users", :force => true do |t|
	      t.column :title,                    :string
	      t.column :description,              :text
	      t.column :aim,                      :text
	      t.column :created_at,               :datetime
	      t.column :updated_at,               :datetime
	    end
	  end

	  def self.down
	    drop_table "users"
	  end
	end

And run rake to migrate our changes:


	rake db:migrate RAILS_ENV=test

Now we make our title spec form spec pass it time to deal with the projects data, so on to our next test.


	'/projects/new.html.erb should have a form' FAILED
	Expected at least 1 element matching "field#projects_title[name='projects[title]']", found 0.
	<false> is not true.

So here we are being told that the title does not exist so lets create it, our view file now looks like the code below:


	<% form_for @project, :url => project_path do |f| -%>
	  <%= f.text_field :title %>
	<% end -%>

Now we are getting an error relating to our stub previously created mock.


	ActionView::TemplateError in '/projects/new.html.erb should have a form'
	undefined method `title' for #<Proc:0x25664e8>

To fix this we modify our mock to look like the snippet below:


	    @project = mock_model(Project,
	                          :title=>'A cool project')

All we have done here is set the title for our project within our mock, fixing our previously broken test.

Now that we have resolved that issue we should be on to our next failing spec.


	'/projects/new.html.erb should have a form' FAILED
	Expected at least 1 element matching "textarea#project_description[name='project[description]']", found 0.
	<false> is not true.

Again this is pretty straight forward, we simply add a text area field to our view, making our view look like below:


	<% form_for @project, :url => project_path do |f| -%>
	  <%= f.text_field :title %>
		<%= f.text_area :description %>
	<% end -%>

Now we stumble upon another issue with our mock, which recieved an unexpected message:


	ActionView::TemplateError in '/projects/new.html.erb should have a form'
	Mock 'Project_1001' received unexpected message :description with (no args)

we could stub out each of our properties as we go along but to be honest that gets very boring very quick.

Lets get this solved once & for all, we’ll modify our mock_model as follows:


	@project = mock_model(Project,
                        :null_object=>true)

This gets us back on track & strolling on to the next expected failure, our missing aims field:


	'/projects/new.html.erb should have a form' FAILED
	Expected at least 1 element matching "textarea#project_aim[name='project[aim]']", found 0.
	 is not true.

Now with our view looking like the example below:


	<% form_for @project, :url => project_path do |f| -%>
	  <%= f.text_field :title %>
		<%= f.text_area :description %>
		<%= f.text_area :aim %>
	<% end -%>

Our specs are now passing but we still have one step missing from our definitions, we left the submit button out of our spec’s but we specified them here luckly enough, let’s get this test passing.


	<% form_for @project, :url => project_path do |f| -%>
	  <%= f.text_field :title %>
		<%= f.text_area :description %>
		<%= f.text_area :aim %>
		<%= f.submit "Create", :disable_with => 'Creating...' %>
	<% end -%>

We have another failing test


	No action responded to create. Actions: authorized?, current_user, logged_in?, and new (ActionController::UnknownAction)

So we basically need to setup a create method in our project controller, we stub out the response for a later scenario.


	def create
    redirect_back_or_default('/')
  end

Now we are ready for our next step definition, this is a nice easy one.


	Then /^I should get confirmation of the successful creation$/ do
	  flash.should contain "You have successfully created your new project"
	end

Our projects controller looks now looks like the following:


	class ProjectsController & ApplicationController
	  def new
	    @project = Project.new
	  end

	  def create
	    flash[:notice] = "You have successfully created your new project"
	    redirect_back_or_default('/')
	  end
	end

All our steps are now passing, lets quickly clean up our view whilst we have our code in a stable passing state, lets sort out our welcome page.


	<%= link_to "Sign up", signup_path %>
	<% if false == self.current_user.nil? %>
	<%= link_to "New Project", new_project_path %>
	<% end -%>

Now along with our specs & our step definitions all passing, we can safely move on to the next story.

We’ll leave that for the next post, what I will leave for now is an outline of what we need to cover on the next few iterations.

  • When submitting the form the user must be alerted if the title is not present
  • When submitting the form the user must be alerted if the description is not present
  • When submitting the form the user must be alerted if the aim is not present
  • When submitting the form the user must be alerted if the project already exists
  • When submitting the form the user successfully, the project will be save
h1

Jumping on the Rails Pt.3 – Getting Authenticated

July 3, 2009

Carrying on from my last post, I’ll introduce Rest Authentication to the Story Board project. The plugin comes with its own stories & definitions, so it will be a nice learning source for us whilst learning Cucumber & RSpec :)

So to start off with lets install the plugin. Now I’ve experienced some issues with Technoweenie’s branch of the code, so I ended up doing some digging and finding a fork by Ombwa, we’ll install this to get our authentication done quickly.

 script/plugin install git://github.com/ombwa/restful-authentication.git

As per the docs you’ll need to do the following if your using Rails 2.1+:

cd vendor/plugin &&
mv restful-authentication restful_authentication

Now we need the act as state machine plugin.

script/plugin install http://elitists.textdriven.com/svn/plugins/acts_as_state_machine/trunk

Next we need to create our user & sesion models

./script/generate authenticated user sessions \
			--include-activation \
			--stateful \
			--rspec &&
rake db:migrate RAILS_ENV=test &&
rake db:fixtures:load RAILS_ENV=test

Now some of the plugins tests fail, so we need to get those passing before we can tick this off the to do list

First we need to map our session controller, to do this we need to add the code below to route.rb

 map.session '/session', :controller => 'sessions', :action => 'create'

If we’re using activation we’ll need to add the following to the environment.rb file.

config.active_record.observers = :user_observer

And finally we added the following to the ApplicationController

include AuthenticatedSystem

Now there are some tests that may fail, namely the routing related user controller specs, you may see something similar to:

 undefined method `formatted_users_path' for #<Spec::Rails::Example::ControllerExampleGroup::Subclass_2::Subclass_3:0x22f8698>

Simply rename this to new_users_path and do the same for the other methods with the methods with ‘formatted’ prefixed:

  • formatted_users_path
  • formatted_new_users_path

I also had issues with the following user model specs, there are not critical for myself so committed a sin and commented them out. The following where the tests that I had issues with:

  • should route users’s ‘update’ action correctly
  • should route users’s ‘delete’ action correctly

Next we’ll get a run of errors from out view specs. We’ll quickly create an application layout that will help us pass the rest of the restful-authentication’s plugin tests. Most of these are asserting that we have a div.notice & div.error element, the below fixed those tests for me.

<html>
	<head>
		<title>Story Board</title>
	</head>
	<body>
		<div id="notice" class="notice"><%= flash[:notice] %></div>
		<div id="error" class="error"><%= flash[:error] %></div>
		<%= yield :layout %>
	</body>
</html>

One final thing, I came across authentication tests that fail, this is usually due to the records not being reloaded after a creation. Adding the following code to both after_create & after_save calls within the UserObserver class, so that our tokens are correct.

user.reload

Now that all our tests are passing, we’re ready to start delving into the main requirements of the application. The next feature is to allow registered users to create a new project. So well create a new file called registered_users.feature and add the following content.

Feature: As a registered user I must be able to create projects
  In order to create a new project I must be logged in
  As a registered user
  I want I want to be able to create new projects

	Scenario: A registered user must be able to create projects
	  Given I am logged in
	  When I click new project
		And fill in the new project form
	  Then I should get confirmation of the successful creation

We’ll focus on this functionality in part 4 of ‘Jumping on the Rails‘. In the meantime I recommend having a look at the stories and definitions that come packed with Restful Authentication, I’ve found very useful in helping me to improve my own stories and definitions ;)

h1

Jumping on the Rails Pt.2 – RSpec, Cucumber & Webrat

June 27, 2009

Well it’s been a while since I’ve written anything really technical & seeing as Rails is taking up a lot of my personal time, I thought I made sense to put some of my newly found knowledge together.

I thought it best to not go over material that has already been done and very well I might add, I’ll just focus on the things have have interested me most & how to take advantage of them in real world situations. This and the next few posts will focus on developing and application using Cucumber, Rails & Webrat to drive the development process. Before I go on, I’d say that none of this would be possible if not for The RSpec book, I’ve read it for a couple times whilst the beta has been floating about and recommend the book to everyone developing in Rails, if only to see what it has to offer.

Lets start of with a basic application. StoryBoard, allows users to create & manage projects and their features with a focus on capturing features that can be used with Cucumber.


rails PROJECTNAME
cd PROJECTNAME

Now we need to setup our BDD environment


script/plugin install --force git://github.com/aslakhellesoy/cucumber.git &&
script/plugin install --force git://github.com/dchelimsky/rspec.git &&
script/plugin install --force git://github.com/dchelimsky/rspec-rails.git &&
script/plugin install --force git://github.com/brynary/webrat.git &&
script/generate rspec &&
script/generate cucumber

Now that’s all we really need to setup our BDD environment, let start with a basic feature to get our feet wet:


Feature: Users must be able to register to the site

In order to allow new users to join the site they need to be able to view the home page & register.
As a guest user
I want to be able to register to the site so that I can create new scenarios for a project

Scenario: A user must be able to view the welcome page
Given I am not logged in
When I visit the home page
Then I should see the sign up link

Seems reasonable, users should be able to view the home page and see a sign up link, after all no one can register without one.

Now a nice little gift that comes with our plugins is autospec, I added the following to my .bash_profile

export AUTOFEATURE=true

This allows me to test both my specs & step definitions.

Starting script/autospec allows us to run our tests automatically on ever save, which can be a nice time saver for those who forget to test after a change.

You can implement step definitions for undefined steps with these snippets:
1 scenario (1 undefined)

3 steps (2 undefined, 1 passed)
0m0.050s

You can implement step definitions for undefined steps with these snippets:

Given /^I am not logged in$/ do
pending
end

When /^I visit the home page$/ do
pending
end

Then /^I should see the sign up link$/ do
pending
end

Cucumber is nice enough to give us code snippets to use in our step definitions, lets start with the first.

Create the file registration_steps.rb

We’ll cheat here seeing as we don’t need to set anything up, it passes.

Given /^I am not logged in$/ do
end

That gets our first part, lets move on to the next, again cucumber will nicely give us the next step definition, we’ll modifiy to look like the code below.

To take advantage of webrat within our specs we’ll need to add the following to our spec_helper.rb

require 'webrat'
config.include Webrat::Matchers, :type => :views

It should now look something like this:

ENV["RAILS_ENV"] ||= 'test'
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
require 'spec/autorun'
require 'spec/rails'
require 'webrat'

Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}

Spec::Runner.configure do |config|
config.use_transactional_fixtures = true
config.use_instantiated_fixtures  = false
config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
config.include Webrat::Matchers, :type => :views
end

Now for the next step definition

When /^I visit the home page$/ do
visit '/'
end

Ok, we obviously need to setup a route for this one.

map.root :controller => "welcome"

We get another error saying:

uninitialized constant WelcomeController (NameError)

Okay we know we don’t have a controller, how about we cheat and make one just to make things pass for now. Especially as we don’t want to get bogged down with detail.

script/generate spec_controller Welcome index

That will basically create our welcome page for us. We can now move on to the next step definition.

Then /^I should see the sign up link$/ do
response.should contain 'Sign up'
end

Now our tests are back to failing again, we’ll move to the controllers view to iron out our functionality.

Own spec_controller was nice enough to create our view for us, lets open up the view spec and add a spec.


#Delete this example and add some real ones or delete this file
it "should tell you where to find the file" do
response.should have_tag('p', %r[Find me in app/views/welcome/index])
end

Is our first test in our view spec, lets replace this with something more meaningful.


it "should have a sign up link" do
response.should have_selector("a", :content => "Sign up")
end

Here we just want to make sure that we have a page where we can sign the user up. Let get it to pass, remove the index.html from the public directory, the add the code below to your Welcome controllers index view.

<a href="/signup">Sign up</a>

Nice and simple right, now we’re still got alot of work to do but that is what the other stories are for ;) , we’ll follow up with those in the coming posts.

h1

Jumping on the Rails

June 21, 2009

Well on my journey to improve my programming skills & again purely because I’ve been getting tired of using PHP for all my solutions, I recently decided to delve into Rails.

I’d been pointed to it by Ekerete Akpan an old work collegue who uses it quite extensively with his own projects.

I’d resisted from learning the language initially primarily down to the fact that the language seemed to be quite basic, in that I was correct, something I’m regretting as I find it now to be one of the best features.

I initally wanted to create a frontend for Chatterl, using ActiveResource. After fighting with it for a week or so, I ended up scrapping that notion and moving on to another project idea I had kept aside for a little while (Solvius).

I won’t go into detail on the goals of Solvius as the site is already live & a brief summary of the webapp can be found here.

The first thing I did was get my self a copy of The Rails way, I have to say I’ve not used the book much over the past month but it was indepensible when it came to helping me learn the basics. I had also picked up copies of ‘Agile Web Development with Rails‘ & ‘Rails for PHP Developers‘, though these proved to be little help & ended up being frustrating reads as they both presumed the reader had basic knowledge of programming methodologies.

By this time I had built the basic functionality of Solvius, allowing users to join the site and create and solve problems, using the active as authenticated plugin. My journey was far from over, I wanted to add ReCaptcha & a little JQuery to the mix. I got a little excited thinking that I could get my hands dirty but low and behold there were plugins for both of these features also :D . Such things are a rarity in the PHP world and having spent a great deal of time there, the PHP side of me felt robbed, whilst the code monkey in me was pleased that I could deal with more direct problems.

All though my inital experience was a pleasant one, I wanted to improve on it further. I’ve been using TDD for a while and played around with Test::Unit for a bit but wasn’t really happy using it, I decided to go for my next book purchase ‘The RSpec Book‘. I have to say reading that was an eye opener, not only from a BDD newbie stand point but also from a coders point of  view, the book helped to improve my coding style and gave me a few cool ideas to play around with when I get the chance.

I started introducing RSpec & cucumber into Solvius about a week ago & already started to reap the benefits, primarily being able to implement functionality from a users point of view rather than my techie one, along with having a point of reference and an enhanced sense of confidence in implementing new functionality.

I’ve read ‘The RSpec Book‘ a couple of times now and will hopefully get the chance to use Cucumber & RSpec in my next pet project. For the moment though I’ll focus my time on improving Solvius & improving my Rails skills in general. Although it feels as if I have picked up the framework pretty quickly, there is still a host of things to grasp & learn.

I’m hoping I’ll have enough time to create a serious of posts, outlining the whole development process using Rails & the tools I’ve picked up over the course of my Rails journey.

h1

Latest project – Solvius

June 7, 2009

Well it’s been a while since I’ve written a post, mainly due to the amount of time I’ve spent learning Rails & working on Solvius.

After reading “Pragmatic Thinking and Learning: Refactor Your Wetware“, I decided to create a program to store all the problems I come across over times, storing them in a solutions log of sorts. For one reason or another I had put it off.

Fortunately I came up with some free time & decided to finally write the application in Rails, I’m new to Rails & as some of you may know I rarely miss the chance to kill two birds with one stone.

It didn’t take long to create the basic functionality, two weeks at the most, the last few weeks I’ve spent learning Cucumber & RSpec, but thats another post. I’ve finally uploaded the application to my host & setup some basic data, over the next few weeks I’ll incrementally add new functionality to the site.

It’s been an enjoyable experience, I must say I’ve become a total convert to rails (i’ll leave that for another post) & have picked up a crap load of knowledge over the past month of a half learning. Hopefully in the coming weeks I’ll write up my notes and experiences but for now I thought I’d quickly go through what Solvius allows people to do & some of the plans I have for it in the future.

Why

Well as I previously mentioned Solvius was inspired by “Pragmatic Thinking and Learning: Refactor Your Wetware“. It’s primary goal is to help people track and store problems & solutions that we come across in our day to day lives. I’ve lost count of the amount of times I’ve come across a problem that I’ve solved but know I’ll have to go digging for the solution.

The cool thing about solvius is that the application can be used to store all kinds of problems and solutions, whether it be some kind of novelty puzzle to some a professional or academic conundrum.

At the moment the application is in beta, so invites are needed before you can signup, hopefully once all the kinks are ironed out and I have the time to improve the design, the site will be open to all.

Features

  • Create problems
    Allows a user to create a public or private problem
  • Solve problems
    Registered users are able to solve public problems, as well as their private ones
  • Make problems private
    Not everyone likes their problems out in the open

Future Features

  • Invites via twitter
    Will be able to tweet @solvius which will mail out an invite
  • Suggest solutions
    Users are able to suggest solutions for public problems
  • Solution & problem search
    Registered users will be able to search for specific types of problems & solutions
  • Facebook Connect
    Peoples will be able to register via FBConnect
  • Tweet updates
    Updates when problems are solved
  • Problem/Solution groups
    Users will be able to join specific problem/solution groups to help in mass problem solving.

Feel free to check out the site out  or tweet @solvius with any suggestions or ideas.

h1

SimplePie & ZendFramework

April 21, 2009

I\’ve been working on my old site the past couple of days and needed to integrate a blog aggregator for my wordpress blog.

Instead of doing it all from scratch & reinventing the wheel, I decided to integrate SimplePie into my Zend Framework project.

Listed below are the steps I needed to get  SimplePie into Zend Framework.

  • Download SimplePie
  • Rename simplepie.inc to SimplePie.php & copy to the library directory of your ZF project.
  • If you want dates you will also need idn/idna_convert.class.php
  • Rename idna_convert.class.php to convert.php & create a directory called \’idna\’ within the library directory
  • Move the newly renamed convert.php & npdata.ser to library/idna
  • Now we are ready to utilise SimplePie within our project.

Below are excerpts from my project, hopefully it will help illustrate how to utilise SimplePie once you have made the necessary changes.


class BlogController extends BaseController {

	function init() {
		$feed = new SimplePie(\'http://baphled.wordpress.com/feed\');
		$feed->init();
		$this->view->title = $feed->get_title();
		$this->view->items = $feed->get_items();
		parent::init();
	}
	/**
	 * The default action - show the home page
	 */
	public function indexAction() {
	}

}

Above we instantiate SimplePie with the URL to our RSS feed, we then initialise our feed & retrieve it\’s title & items, assigning the variables to the view.

The next segment of code is for the index.phtml and basically populates our content with our aggregated blog feed.

foreach($this->items as $item): ?>
	<div class=\"chunk\" style=\"padding:0 15px;\">
		<h4><a href=\"{$item->get_permalink()}\" target=\"_blank\"><?php echo $item->get_title(); ?></a></h4>
		<?php echo $item->get_description(); ?>
		<p class=\"footnote favicons\" align=\"center\">
			<a href=\"<?php echo $item->add_to_blinklist(); ?>\" title=\"Add post to Blinklist\"><img src=\"/images/favicons/blinklist.png\" alt=\"Blinklist\" /></a>
			<a href=\"<?php echo $item->add_to_blogmarks(); ?>\" title=\"Add post to Blogmarks\"><img src=\"/images/favicons/blogmarks.png\" alt=\"Blogmarks\" /></a>
			<a href=\"<?php echo $item->add_to_delicious(); ?>\" title=\"Add post to del.icio.us\"><img src=\"/images/favicons/delicious.png\" alt=\"del.icio.us\" /></a>
			<a href=\"<?php echo $item->add_to_digg(); ?>\" title=\"Digg this!\"><img src=\"/images/favicons/digg.png\" alt=\"Digg\" /></a>
			<a href=\"<?php echo $item->add_to_magnolia(); ?>\" title=\"Add post to Ma.gnolia\"><img src=\"/images/favicons/magnolia.png\" alt=\"Ma.gnolia\" /></a>
			<a href=\"<?php echo $item->add_to_myweb20(); ?>\" title=\"Add post to My Web 2.0\"><img src=\"/images/favicons/myweb2.png\" alt=\"My Web 2.0\" /></a>
			<a href=\"<?php echo $item->add_to_newsvine(); ?>\" title=\"Add post to Newsvine\"><img src=\"/images/favicons/newsvine.png\" alt=\"Newsvine\" /></a>
			<a href=\"<?php echo $item->add_to_reddit(); ?>\" title=\"Add post to Reddit\"><img src=\"/images/favicons/reddit.png\" alt=\"Reddit\" /></a>
			<a href=\"<?php echo $item->add_to_segnalo(); ?>\" title=\"Add post to Segnalo\"><img src=\"/images/favicons/segnalo.png\" alt=\"Segnalo\" /></a>
			<a href=\"<?php echo $item->add_to_simpy(); ?>\" title=\"Add post to Simpy\"><img src=\"/images/favicons/simpy.png\" alt=\"Simpy\" /></a>
			<a href=\"<?php echo $item->add_to_spurl(); ?>\" title=\"Add post to Spurl\"><img src=\"/images/favicons/spurl.png\" alt=\"Spurl\" /></a>
			<a href=\"<?php echo $item->add_to_wists(); ?>\" title=\"Add post to Wists\"><img src=\"/images/favicons/wists.png\" alt=\"Wists\" /></a>
			<a href=\"<?php echo $item->search_technorati(); ?>\" title=\"Who\'s linking to this post?\"><img src=\"/images/favicons/technorati.png\" alt=\"Technorati\" /></a>
		</p>
	</div>
<?php endforeach; ?>
h1

Lighting up the tunnErl Pt. 9 – The Gotchaz

March 13, 2009

Over the years I’ve become pretty good at picking up on errors, learning a new paradigm as well as a new language helps to introduce a lot more of these than usual so I’ve put some of the more common errors I have come accross to help others pick up on the errrors that had me baphled from one extent to another.

  • function_clause – generally means that the result was not matched for one reason or another, make sure you are retrieving the result you expected.
  • noproc – either the process is not started or the node cannot communicate with it, first try net_adm:ping(hostname). then check to see if the process is alive erlang:is_process_alive(Pid).
  • undef - Happen when a function in module does not exist, the module is not loaded or not exist at all. Maybe the function name has been misspelt.
  • ‘*.app not found’ – this typically means that the application can not be found or it is not included, check that it is part of you dependancies and that has been started properly.
  • error:{badfun,ok} – EUnit based error missing comma, usually because assert is returned in wrong place.
  • syntax error before: ‘end’ – have added an “,/;’ proceeding the end
  • none:error:internal error in beam_asm – Sinan based error, happens when code is out of sync, best solution is to kill sinserv and run sinan again.

As time goes by I’ll continue to add more, what this space. If anyone has come across a gotcha that i’ve missed drop me a line, i’ll be more than happy to add it to this list.

h1

Lighting up the tunnErl Pt.8 – Testing processes

March 13, 2009

Well after months of trying to get my head around running units around a process I think I have it sussed.

Simple unit tests
Well I’m sure you have seen these type of erlang tests before

-module(test_foo).
-include_lib("eunit/include/eunit.hrl").
foo_test_() ->
[?_assertEqual("foo",say("foo")),
?_assertEqual("bar",say("bar"))].

The above code basically asserts that the method say returns what we expect. Okay so now what if we want to setup a process, lets say chatterl:start() and test its functionality, how would we do that? well it took me a while to get my head around this part.

I have noticed that if any processes are left alive during a unit test, the process will still be active whilst the other tests run, so if for some reason you find previous test cases failing where they were initially passing, first check that you have killed all the necessary processes in all units.

Creating simple units was a walk in the park and nothing really different from the standard units I’ve created in various C clones. The doozy was creating units that focus on a specific process rather than a method or function.

Testing processes

chatterl_mid_man_basics_test_() ->
[{setup, fun() ->
chatterl:start() end,
fun(_) ->
chatterl:stop() end,
[{timeout, 5000,
fun() ->
?assertEqual(<<"Illegal content type!">>,
check_json(mochijson2:decode(chatterl_mid_man:user_list("text/json")))),
?assertEqual([],chatterl_serv:list_users()),
?assertEqual({struct,[{<<"clients">>,[]}]},
check_json(mochijson2:decode(chatterl_mid_man:user_list(["text/json"]))))
end}]}].

The above test is from chatterl’s test cases, the test starts chatterl on setup, waits 5000 msecs using a timeout & runs the units within the final fun/0. Once our tests have run we need to stop chatterl (which will drop all its connected processes). I’ve used a timeout because it seems the processes I am working with need some time to be dropped before the next test is started, I’ve noticed that if this wasn’t done I’d get all kinds of unrelated errors or complaining that the process is still alive.

Though this process seems cumbersome, especially as I’m used to a single setup/teardown method which does the same thing each time a unit is run, the above handles our tests pretty well.

For the extra curious, you can find test cases used for chatterl/libs/chatter/src/chatterl_test.erl @ github.

You can also checkout Kevin Smith’s code as he seems pretty up to scratch with his tests membox is a good place to start.

h1

Lighting up the tunnErl part 7 – Chatterl meets Nitrogen

March 13, 2009

Well it’s been a has been a while since I have posted a blog, mainly down to the amount of time I’ve been spending playing around with Chatterl & Nitrogen. I have come a way since first playing around with Erlang I decided a few months ago to make Chatterl my main personal project. I played around with BeepBeep around the same time as Nitrogen, for one reason or another I picked up Nitrogen quite quickly and decided to run with that as Chatterl’s prototype frontend.

I have to admit though I have never really been a fan of event driven frameworks, especially those that mask mark up language but after a day or two of messing around with Nitrogen I found it quite a pleasant experience.

The learning curve can be somewhat steep as the documentation is not as good as it could be, I also have issues with having the root directory starting with /web/, so the admin directory would be http://blah.com/web/admin, hopefully this will be changed in the near future. Besides those minor gripes Nitrogen is starting off as a nice framework.

Well I wish I had some time to run through a little tutorial, for the moment the best I can do is show you how I implemented some of the functionality need for Chatterl’s front-end. Below is a list of features I’ll be concentration on:

  • Main body
  • Validate Message
  • Client Panel
  • Message Panel
  • Groups Body
  • Users Panel

We’re working with Chatterl’s Web Interface API (CWIGA) which works on 127.0.0.1:9000, I prefer JSON so I’ve only implemented functionality to handle this. The implementation code is very similar to that I’ve written about previous so I wont waste bytes (see Twitterl), I’ll just say that we need to connect to CWIGA via HTTP.

For the curious, the code can be found the functionality needed to interact with Chatterl can be found in the file chatterl_cwiga_handler.erl. The actual calls are defined within Chatterl interface.

Now we have the basics for interacting with Chatterl over HTTP, lets have a look at how this all ties in with working with Nitrogen. I won’t go over how Nitrogen works as that part is pretty well documented in a few placed (Nitrogen, Jón Grétar) but I will explain the functionality I’ve implemented for chatterl_nitrogen.

Main body
body() ->
ChatBody = [ #panel { id=messageBodyPanel} ],
Left = [ #panel
{ id=leftPanel,body=[client_panel(),message_panel(),
[#panel { id=groupsPanel, body=[groups_body()]}],users_panel()] } ],
Right = [ #panel { id=rightPanel, body=[ChatBody] } ],
Container = #panel { id=containerPanel, body=[Left,Right] },
validate_message(),
wf:render(Container).

Ok now what the hell is all that??? Well it doesn’t look like it but this is how Nitrogen renders HTML, we structure our HTML using Nitrogen’s elements & actions which in turns renders our pages for us.

Firstly we define the containers needed to organise the chat window, Allowing me to have the chat box on the right, whilst having all the other features (message box, groups list, etc) on the left. As you may of already guessed the element #panel represents a div with XHTML, id’s act as you would expect & can be manipulated with CSS as usual.

Validate Message
validate_message() ->
wf:wire(messageTextBox, messageTextBox, #validate
{ validators=[
#is_required { text="You forgot to submit a message." },
#min_length { length=2, text="Title must be at least 2 characters long." }]}).

Here we use the method wf:wire which basically connects an element to another, so a input box could be ‘wired’ to a submit button. In this case we want to make sure that we validation only when the messageTextBox has data, validate it. The next two lines do exactly that, firstly #is_required makes sure that we actually have a value, whilst #min_length gives a validation error if it has not been adhered to. The response are triggered by AJAX using JQuery, so as soon as an event is caught it is handled asynchronously.

Client Panel
client_panel() ->
[#panel { id=clientPanel, body=[get_client_panel()]}].

This panel is pretty straight forward, it simply defines a DIV elements which calls get_client_panel/0 which in turn determine what actions are needed. This method will be explained better shortly.

Message Panel
message_panel() ->
[#panel { id=messagePanel, body=[
#label { id=messageLabel, text="Message:" },
#textbox { id=messageTextBox, text="", style="width: 100px;", postback=group_message}
]}].

This is the the DIV element that is used by the user to send messages to chatterl. We have a couple of things we have encountered yet, our postback, which will be explained shortly & two elements (#label & #textbox). Pretty straight forward right. What about this postback thingie? Well postbacks are in fact our AJAX calls, allowing the user to interact with the systems backend seemlessly. We’ll see how these are handled in the Events section.

Groups Body
groups_body() ->
SelectedGroup = wf:q(groupsDropDown),
#panel { class=groupsPanel, body=[
#h1 { text="Groups" },
#label { text="Select a group to join:" },
#dropdown { id=groupsDropDown, value=SelectedGroup,
options = [ #option { value=Group, text=Group }
|| Group <- chatterl_interface:get_groups()],
postback=join_group} ] }.

Here we have an panel which allows users to select a group to join, we again use a postback to handle our AJAX call & use the chatterl_interface module to retrieve a list of groups from Chatterl.

Users Panel
users_panel() ->
SelectedUser = wf:q(usersDropDown),
[#panel { id=usersPanel, body=[
#label { id=usersLabel, text="Select a user:" },
#dropdown { id=usersDropDown, value=SelectedUser,
options = [ #option { value=User, text=User }
|| User <- chatterl_interface:get_users()] } ]}].

This should be pretty self explanatory as it is more aless the same functionality as groups_body/0.

Get client Panel
get_client_panel() ->
case wf:session(client) of
undefined ->
wf:wire(groupsPanel, #hide {}),
wf:wire(messagePanel, #hide {}),
client_login_panel();
Client ->
wf:comet(fun() -> update_status("messages",1000) end),
wf:wire(groupsPanel, #show {}),
wf:wire(messagePanel, #show {}),
client_logout_panel(Client)
end.

Well this method basically checks to see if a user is connected if they are then we display the messagePanel, groupsPanel along with groupsJoinedPanel. We allow the messages panel to update, giving the user the most up to date messages from Chatterl. We lastly set the client_panel to client_logout_panel/1, which we’ll have a look at shortly, this method basically allows the user to disconnect once they have connected successfully to Chatterl.

Client login Panel
client_login_panel() ->
#panel { id=loginPanel,
body=[
#label { text="Client name:" },
#textbox { id=userNameTextBox, text="", style="width: 100px;", html_encode=true, postback=connect }]}.

Client logout panel
client_logout_panel(Client) ->
#panel { id=logoutPanel,
body=[
#inplace_textbox { id=userNameTextBox, text=Client, html_encode=true, start_mode=view },
#button { id=theButton, text="Disconnect", postback=disconnect }]}.

This method is pretty much the same the the client_login_panel/0, with 1 small change, instead of connecting to Chatterl we want to disconnect. The principle is still the same, create an event, passing the postback (disconnect).
which in turn disconnects the user from Chatterl.

Update status
update_status(Type,Timeout) ->
process_flag(trap_exit, true),
case Type of
undefined -> ok;
"messages" -> loop_messages(Timeout);
{"general",StatusType} -> loop_status(Timeout,StatusType);
_ -> io:format("Unknown loop type: ~s",[Type])
end,
wf:comet_flush(),
update_status(Type,Timeout).

Events

Connect Event
event(connect) ->
[Client] = wf:q(userNameTextBox),
case chatterl_interface:connect(Client) of
{ok,Message} ->
wf:flash(Message),
wf:session(client,Client),
wf:update(clientPanel, #panel { body=[get_client_panel()] });
{error,Error} -> wf:wire(#alert { text=Error })
end.

Above is the actually postback method call event(connect) which utilises chatterl_interface:connect/1 allowing us to make a connection to Chatterl directly. If the request is successful we create a new session wf:session(client,Client) & update our clientPanel so that they user can logout as you would expect.We do this by using the wf:update/2 method that dynamically changes XHTML elements on the fly.

Disconnect Event
event(disconnect) ->
case chatterl_interface:disconnect(wf:session(client)) of
{ok,Message} ->
wf:flash(Message),
wf:session(client,undefined),
wf:session(selectedGroup,undefined),
wf:update(messageBodyPanel, #panel { body=[] }),
wf:update(clientPanel, #panel { body=[get_client_panel()] }); % Should redirect here.
{error,Error} ->
wf:wire(#alert { text=Error })
end.

Well there’s the disconnect event, nothing to dramatic here, simply unregister the client & selectedGroup cookies& update the page so that the client_panel is set back to its default.

h1

TDD Patterns

January 28, 2009

Here are a few tips that I use myself to help keep myself on track, Like the other TDD related notes, I’ll keep these updated as time goes by.

It is often easy to get overwhelmed by a task & lose sight of what you as supposed to be testing and how to go about it, below are some pointers/patterns to help you run through the TDD process.

One Step Test
Each test should represent 1 step towards our overall goal.
If a test can not be found to do this, create one.

Starter Test
What test do we start with? Pick up a test that will teach you something about the system & will be quick to get working.
The One Step Test plays a hand in this, after realising the starter test it becomes easier to realise other test cases.

Learning Test
Use tests to help yourself learn about a particular architecture, by testing a library/framework you can find yourself becoming quite accustomed to it uses, not to mention checking that the API works as you expected.

Another Test
If a new idea is realised, write a test for it, its easy to get taken off of track so by writing down new tests. We retain the ideas but keep on with our present task at hand.

Regression Test
When a defect is reported the first things we do is, write the smallest possible test that will fail, once run will be repaired.
Gives the client a concrete way of explaining what is wrong and what they expect.
On a small scale regression testing can help you to improve your testing.

Break
Having a problem realising a solution or implementing a test, take a break, take a walk, get a drink, have a rest. Anything to allow you to momentarily detach yourself from the problem at hand. This normally alleviates the issue of hitting a brick wall. Generally the more fatigued the worse judgement calls, spiralling into worse your decisions and the issues that arise because of it.