Copyright © 2010 The G String. All Rights Reserved. Snowblind by Themes by bavotasan.com. Powered by WordPress.
Archive for August, 2009
I’m glad to be working on some Rails projects with two cool London-based agencies next month. Starting out with a return to Delete London, followed by a project at Head London. Bring it on!
If you have a project starting in October, please let me know.
Continue Reading »
I approached the task of undertaking market research for my new music start-up company in the typical programmer way: I made a website. I wonder how many of life’s problems I would approach in this way; but having a website seems like a good start.
I wanted to canvass the opinion of friends and colleagues on the habits of their on-line music consumption, particularly pertaining to music subscriptions, which is a central idea within my business plan. I knew that I wasn’t an expert in marketing, so I wanted to design a form that would allow users to customise it as they went; so that they could add choices for others to select as they went along. I accomplished this using a standard ruby on rails website, a form, and some AJAX.
Defining my data
First of all, I wrote down a basic entity-relationship diagram on the back of an envelope of what I wanted my models to look like. I knew I was going to ask a load of questions, so I made a box to represent them. I also knew that each question would have a number of choices to select from, such as ‘Agree’ and ‘Disagree’, which is a one-to-many relationship. Next, I hoped that someone would respond to the questionnaire, by associating a subset of choices with the questions I had asked, so I made a box for ‘responses’. There were multiple choices in the questionnaire and hopefully multiple choices so I needed a many-to-many relationship.
I even threw in a user model to store a respondant’s age and location; although it was probably overkill.
Iteration #1 – Make some models
I could then ask rails to do lots of work for me using the generate scripts.
ruby script/generate model Question text:text
ruby script/generate model Choice text:string, question_id:integer
ruby script/generate model Response question_id:integer, choice_id:integer, user_id:integer
ruby script/generate model User age:string, location:string
Normally I’d start with a scaffold, but in this case I didn’t want all of the CRUD features for questions and choices available on-line. Instead, I borrowed a trick I’d learnt from hacking around on the hyperactive CMS project to ‘seed’ the database by loading in data from YML files, rather like the way fixtures work in the unit tests.
Before I started-up webbrick, I wrote down some unit tests to ensure that the relationships were working the way I expected them to, and to ensure that the basic validation on the models were working correctly.
class QuestionTest < ActiveSupport::TestCase
test “required fields” do
question = Question.new
assert_equal false, question.save
question.text = ‘hi’
assert question.save
end
test “question has choices” do
assert_equal false, questions(:one).choices.empty?
assert_equal choices(:emusic), questions(:one).choices.first
end
end
The first test makes sure I can’t save a question without the question’s text being populated. Rather than testing the rails validation framework, this gives me the peace of mind that I remembered to write the validation, and the test will tell me if I accidentally remove the validation in a future re-factor.
The second test ensures that I have my model relationships configured correctly, so that I can access a question’s choices via an attribute.
I could then go away and implement my model:
class Question < ActiveRecord::Base
validates_presence_of :text
has_many :choices, :order => ‘choice_index, text’
end
I approached the remaining models in the same way. Before I could see anything in a browser, I needed to populate the database using the YML files I mentioned before. So I wrote the following rake task to populate the database (lives in lib/tasks).
namespace :db do
desc “Load seed fixtures (from db/seed) into the current environment’s database.”
task :seed => :environment do
require ‘active_record/fixtures’
Dir.glob(RAILS_ROOT + ‘/db/seed/*.yml’).each do |file|
Fixtures.create_fixtures(‘db/seed’, File.basename(file, ‘.*’))
end
end
end
Which allowed me to structure the data of my questionnaire in the following way:
(db/seed/questions.yml)
three:
id: 3
text: ‘What music websites do you currently use?’
(db/seed/choices.yml)
emusic:
question_id: 3
text: ‘E-music’
napster:
question_id: 3
text: ‘Napster’
spotify:
question_id: 3
text: ‘Spotify’
I could then run rake db:seed and my database would be populated with the questionnaire data. I could now fire-up a browser and begin programming the view.
Iteration #2: First form
The next job was to create a form that would allow my respondents to view the questions in my database, along with the choices, and make some responses. I had a bit of plumbing to do here, without the scaffold in place, so I generated a controller, added some views and updated by routes.rb.
Once I had a view, I could create a form. I decided to treat the form as an ordered-list, so I created a partial that would supply the HTML for each question and enclosed it in a OL and LI tag:
<% form_tag ‘/respond’ do -%>
<ol>
<% @questions.each do |q| %>
<%=render :partial => ‘questionnaires/question’, :locals => { :q => q } %>
<% end %>
</ol>
<div id=”submit”>
<p>That’s all for now! Press this button to complete the survey.</p>
<%=submit_tag ‘Submit Questionnaire’%>
</div>
<% end -%>
This approach immediately posed the problem of how to read in the form data, when the view doesn’t know what questions and choices are being visualised in advance. The solution rested in the correct naming convention that allowed rails to convert the form data into a manageable collection. I wanted a collection of responses, that would each contain a collection of those selected choices a user had made, and this is done by naming each input ‘responses, each containing a collection of choices organised by their question_id.
So I could code my question partial (q is the current question):
<% question_name = ‘responses’ %>
<li class=”question” >
<%=label_tag ‘text’ + q.id.to_s, q.text%>
<%=text_field_tag question_name, nil, {:id=> ‘text’ + q.id.to_s} %>
</li>
However, I realised that I couldn’t determine what type of question is was yet; should I display a text-box, a check-box or a radio-box? Back to the drawing-board.
Iteration #3: Multiple-choices
I needed a way of determining what type of question I was asking: would I allow multiple responses to the same question (appropriate when asking ‘which of the following…), or only one (agree, disagree). I accomplished this by adding a allow_multiple flag to my question model, which I could then read in the view to determine whether or not to display a checkbox (for multiple responses) or a radio-box (for one-choice). When there were no choices for a question, I would assume a text-box was reuqired, and that is how the age/location fields work.
Once I had updated my fixtures, model and database, I could return to the view:
<% if q.choices.empty? %>
<%=label_tag ‘text’ + q.id.to_s, q.text%>
<%=text_field_tag question_name, nil, {:id=> ‘text’ + q.id.to_s} %>
<% else %>
<p><%=q.text%></p>
<% q.choices.each do |c| %>
<div class=”choice”>
<%=label_tag ‘choice’ + c.id.to_s, c.text%>
<% if q.multiple_choice %>
<%=check_box_tag question_name, c.id, nil, :id=> ‘choice’ + c.id.to_s%>
<% else %>
<%=radio_button_tag question_name, c.id, nil, :id=> ‘choice’ + c.id.to_s%>
<% end %>
</div>
<% end %>
I could now view my form and see the correct input fields being displayed, ready for my controller to save the responses.
Iteration #4: Adding new choices
The main reason for developing a new questionnaire in rails was to allow my respondents to add choices which I hadn’t anticipated, in turn allowing others to choose the same response. This is proving useful for the ‘which music services do you use’ question, throwing-up websites I might not have otherwise heard of and I can now benchmark and investigate.
To add a new choice, I needed a way of distinguishing which questions I would allow new choices for and which I would not, so I added another field to question called ‘allow_new’. I updated my model, fixture, database (and unit test of course!) and was ready to up-date my view.
<% if q.allow_new %>
<div class=”choice”>
<label>Other (please specify)</label>
<div id=”new<%=q.id%>”>
<%=text_field_tag ‘newchoice’, nil, {:id => ‘newchoice’ + q.id.to_s} %>
<%=hidden_field_tag ‘question_id’, q.id, {:id => ‘question_id’ + q.id.to_s} %>
<%=submit_to_remote ‘add_btn’, ‘Add’, :update => (‘q’ + q.id.to_s),
:url => ‘/addchoice’, :submit => ‘q’ + q.id.to_s%>
</div>
</div>
<% end %>
I added a textfield labelled ‘Other – please specify’ and a button with an AJAX action, so that respondants could add their new choice as they went along, without submitting the entire form. In order to achieve that, I used the submit_to_remote button, which in effect allowed me to nest multiple forms within a single form. Although intuitively, I wanted to create additonal form tags to surround the new text field, this approach didn’t seem to work cross-browser and only the one form is needed. Instead, the :submit option is used to tell javascript to serialise all of the form elements underneath the element with the given ID. The beauty is that this element doesn’t have to be a form element- so here I use the DIV surrounding the question, serialising only the text field for the new choice, along with the existing choices (which I later used to pre-populate the choices that had already been selected). I also pass along the question_id in a hidden field, so that the controller knows which question the new choice belongs to.
IE GOTCHAS: Developers beware! This approach of including multiple AJAX submit buttons in IE is very fickle; unless you play by its rules it wont work and you’ll probably waste time trying to figure it out. Don’t fall into these traps:
Iteration #5: Finishing up
I had a working questionniare, but I wanted to ensure that at least the age and location fields were completed, and that any previously-completed form elements were not lost in the event that validation failed.
The first task here is to ensure that the user model validates for this information:
class User < ActiveRecord::Base
validates_presence_of :location
validates_numericality_of :age, :allow_nil => false
has_many :responses
end
Now if I try to call save! on the User class, I’ll get an error in my controller. Using a begin/rescue block, I could now take appropriate action:
rescue
@errors = true
@questions = Question.find(:all, :order => ‘question_order’)
render :action => ‘index’
end
end
I didn’t want my validation to be too sophisticated. Here I used a flag stored in @errors that I check for in my view to display an error message.
To ensure that the form pre-populates with the previous responses, I had to pass the relevant data back out of the params object as the value parameter for the form tag helpers. In the case of the checkboxes, these values would be within a collection that stores the primary key of the choices that had been made, so a little logic was needed to detmermine whether or not to check the box controls:
checked = prevvalue.include?(c.id.to_s) or c.text == params
The second test here checks the new choice created by the AJAX form, determined by whether or not the text in the submitted box matches the newly-created test.
So, an afternoon invested in a new questionnaire and hopefully some intriguing insights into our music consumption habits. If you have any observations about my approach here, or have spotted something that I could have done better or more efficiently, please leave a comment as I’d be glad to know about it.
Of course, don’t forget to complete the questionnaire!
http://mostrated.com/questionnaires/
<% form_tag ‘/respond’ do -%>
<ol>
<% @questions.each do |q| %>
<%=render :partial => ‘questionnaires/question’, :locals => { :q => q } %>
<% end %>
</ol>
<div id=”submit”>
<p>That’s all for now! Press this button to complete the survey.</p>
<%=submit_tag ‘Submit Questionnaire’%>
</div>
<% end -%>
I often use the nifty Google search feature ‘define’ to look-up definitions of dictionary words. There are a few widgets kicking-about on the various desktop environments I use; but none are quicker than firing up my browser and hitting ‘define something’ and receiving a response (apparently something is a single by Lasgo from the album ‘Some Things’, according to Google).
However, I discovered that if you don’t type something in quickly enough, an AJAX trigger calls up Google to suggest some definitions, presumably stored in a trie somewhere on-line, to auto-complete the form. Interestingly, it doesn’t even wait for a first-letter suggestion, so typing in ‘define’ and waiting a few seconds gives you the top-ten words people want definitions for.
Assuming that people looking for definitions are in want of understanding of a given phrase, or want a better, clearer representation of these concepts, it makes for an interesting list:
My definition: The prevailing free-market idealology of the last thirty years. Big business can go where they like, in a post-nationalist, centralised, hierarchical and acutely unequal world.
Quite why the uneducated, semi-literate masses would be interested in a system that is designed for their superior plutocratic banking masters seems a mystery.
It makes sense that narcissists would neglect to learn this definition until it had reached an advanced stage, as it would require a sufficient degree of empathy for them to consider how other people perceive them in the first place. Of the definition, they probably thought ‘that doesn’t apply to me’, before returning to Twitter to tell their followers what they had for breakfast that morning.
Huey Lewis’ definition: “The power of love is a curious thing, it makes one man weep and another man sing”.
We might have hoped that Love would have made it in the list; there is still some interest in this essential emotion it seems. The narrow definition thrown-up by Google seems both consice and completely inadequate. Does anyone know what this thing is? Spinoza says rather un-poeticly, “Love is joy, accompanied by the idea of an external cause” and goes on to say that “love and desire can be excessive”. Schopenhaur gives the game away when he says: “Every kind of love, however ethereal it may seem to be, springs entirely from the instinct of sex”. Perhaps if he were alive today and working at Google, he’d put ‘Did you mean : sex‘ above the search results.
No, I think Google’s got the wrong idea here. People are searching for culture because they are in want of it: they’re trying to justify an existance on reality TV, auto-tuned boy/girl-bands, sports enacted by millionaires and naff video clips on-line. Perhaps they were hoping for the definition: “watching operas through Twitter”.
I thought this was an interesting definition, because I thought marketing was something to do with questionnaires, cold-calling, advertisements and sponsorships. But as it goes, its nothing to do with that at all- its all just selling shit. Presumably our narcissist works in marketing? If so I’m sure he’d have something to say to improve that definition. Maybe: ‘the essential activity of producing jingles, brochures and slogans that enables informed buying decisions, without which the world would come to an end’.
Must we imagine a scene when a boss or someone’s dad says “You should change your attitude- get motivated”, and some hapless person who doesn’t really know what this means, rather than asking someone, reaches to their keyboard to ask Google what it is? Hardly self-actualisation. I suppose we must credit Google users for being bothered to find out what its definition is.
Of all the things two human beings could communicate, this definition is illustrated by some obscure allusion to Cold war Russia. Are people searching for a definition of communication on Google, because somehow, e-mail, twitter, facebook and instant messaging don’t capture the range of human emotion in communication? Do we want to communicate more effectively? Is anyone actually listening? Do you love me baby? Leave me a comment. Don’t forget to rate!
A corporate cover-up? Maybe Google isn’t just censoring China. Of course, people are searching for definitions to the spectrum of mental sufferings we know today as stress; or the deep contradiction we feel in ourselves that maybe we amount to more than hamsters on a wheel, struggling for bits of paper, in contrast with our natural inclination to live, thrive and survive, with possibily a bit of room for the appreciation of the sublime beauty of life. But don’t worry about stress. Take a deep breath and carry on. Of course your job is important! Without you, the entire globalised word would come crashing down.
Ahh yes, the recession. The definition of (1) neglected to mention that part. The good news is that Google predicts the recession is only going to last a year in the worst case.
Who would require clarification on the definition of recession? Presuambly not wind-farm workers out of a job. Maybe MPs trying to play down the financial problems of the last year are looking for some positives in the definition, maybe a blog for ‘top ten tips for beating a recession’.
A weak definition when read up to the first five words in, that improves slightly by the end. A rather negative definition too; absence of disease doesn’t necessarily indicate health. According to the World Health Organisation, depression is the second-largest thief of disability-adjusted-life-years, or the sum of time lost to a disability, in the 15-44 age group, and is projected to be for all ages by 2020. What do they know that we don’t? That a futureless, indebted, cultureless, stressed, under-motivated, sex-mad, unemployed, mis-communicated, bunch of marketing narcissists can’t get it together and all end up depressed? Define gutted.
The web’s great isn’t it? We don’t need art, philosophy, community or religion to help us understand the word: just ask Google!
Continue Reading »I haven’t found sufficient reason to listen to my inner sceptisism about the awful writer’s bolemia website, widely known as Twitter. I’m ridiculously proud of my forty-something followers, some of whom are not even real people (I’m referring to websites and places of work, I’m not making a jibe at my own followers- goodness gracious do you think I’m MAD?), and I like having my Twitter updates appearing on my blogs. Its very fashionable in the blogging world- a little blog inside your blog. Like Russian dolls, except if the smallest doll breaks, the bigger one is screwed too.
I’ve seen a dip in traffic today, probably because of the massive denial of service attack on Twitter today, causing the Twitter link to timeout, making my blog look like its crashing too. Admittedly, my own server would likely collapse like a tower of jamjars should any hacker target it, but I’m really starting to wonder whether its a good idea to have Twitter on my homepage. I never visit someone’s blog and read their Twitter updates, let alone follow them- that’s most likely to happen while reading Twitter itself.
Yet I find myself reluctant to change the situation. In all truth, I think Twitter is rubbish, but I’m hooked in an unpleasantly high degree.
Anyone had any good workarounds for embedding Twitter in their blogs and avoiding such problems? I’ve stuck my Twitter javascript code at the bottom of the HTML near the </body> tag; would it be better to pull-in the RSS of my tweets within my Rails view?
Continue Reading »A request for an up-to-date copy of my C.V. for a Ruby on Rails contract turned into a top-to-bottom website overhaul, costing the entire day to sort out. I have been operating dangarland.co.uk for over a year, jotting down occasional observations about web development. In that time, I ran the same default installation of WordPress, missing out on the several very useful features for the casual blogger. There is nothing like a change of scenery to rejuvinate any undertaking, and I hope that this wordpress upgrade and site re-organisation achieves that. I had seen visitors dropping off, and last month was the first month in ages that I failed to post a single entry. Granted, when you have a Twitter account and two other blogs, something has to give, and maybe there is more to write about in music.
My upgrade wasn’t totally straightforward, lasting much longer than the five-minutes claimed on the packet. After downloading and unpacking the latest tar file, I upgraded my database alright, but whenever I tried to visit a blog entry page, apache would 404. After a bit of confusion I remembered that the .htaccess file is required for WordPress to convert URLs into something it can use with PHP.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php
</IfModule>
# END WordPress
After that, and its all browser-based tweaking. A nice enough install. I peruse the themes, bored with the WordPress default, and settle on this tight and modern white on black theme. I particularly like the AJAX drag+drop CMS that builds the menus by dragging widgets from a list into the relevant section. Notice the RSS feed reguritating content from dangarland.me.uk, my tag cloud and even a twitter feed. None of this is news to most- but I’ve brought my site forward a year or two towards the present trends in a few minutes.
The site required a bit of re-organising too. I had a bunch of static HTML files, hand-authored in emacs from about 1997 that I had previously been maintaining, but were seriously out of date and looked a decade out of date. With my competitors downloading swish web 2.0 themes for nothing, it had to go; so I’ve concatenated the experience, education and interest sections onto the CV page, leaving my project work on its own page. The site now has three distinct levels of content that are updated more or less regularly; the RSS feeds of blogs, comments and Twitter will display changes most, and live on the top-left and bottom of the blog; The blog itself, which might expect an update a month right now, sits in the middle, gradually filling with wisdom; and finally the projects page, which will get added to every job I actually take.
Anyway, if you prefer the layout or just want to say hello please leave a comment, otherwise listen out for the next Ruby on Rails adventure I take on! I’m currently working on a little scheme of mine for a music website, which I think will require some collaboration in the near future, so be sure to listen in to my RSS if you’re a developer and interested in music web projects.
But anyway, well done WordPress for making software good enough for a casual blogger to make a website in a few hours with the least amount of fuss. In fact, you are too efficient: I started out the day upgrading to 2.8.2 and already I’m behind the latest version… calm down.
Continue Reading »