Who’s Online?

So, how do you tell who’s online? If you’ve been subjected to the abomination that is myspace you’ll have seen that ‘online now!’ indicator. Well, here’s how I solved that one recently.

First up, here’s a list of all the commands you’ll want.

rake create_sessions_table
script/generate model online
script/generate migration add_user_id_to_session_table

move to db-sessions

rake create_sessions_table

First, if you want to make this easier for everyone, move your application over to db-based sessions. It’s relatively painless, and is much faster than file-system. If you’re on memcache, you’re probably beyond this article.

Now edit your config/environment.rb and add/alter this line:

config.action_controller.session_store = :active_record_store

create the model

script/generate model online

Now you’ll need to make a model so we can access all that lovely session data across all sessions.

Edit the model and set the table name to ‘sessions’. while you’re there, create the association for the user

belongs_to :user
set_table_name ‘sessions’

modify the table

script/generate migration add_user_id_to_session_table

The rake task we ran before added a table called sessions with a session_id, data, and updated_at fields. We want to add the user ID to this. In your migration, you want to add a user_id column (change this as necessary for your own setup.)

add_column :sessions, :user_id, :integer

set the user id in your app

now, edit or create a before_filter in your app that sets up the current user, and set the user_id like this:

sess = Online.find_by_session_id(@session.session_id)
sess.update_attribute(:user_id, @session[:user_id])

Of course there are a metric crapton of ways to do this. You could even hook into it from an image-bug in the page and a specialized action somewhere.

now, show me the mon(k)ey!

Now view your online users! This last step, I’ll leave to you, because it can be done in many ways, dependent on database and coding style.

Online.find(:all, :conditions=>['updated_at > ?', Time.now - 5.minutes])

Remember to add indexing to the user_id field, too.

How else do people do this? What about on page cached sites? (I have my own solution, but that’s “a whole `nother article..”)

 

More Cracked-Out Scaffolding: element.twisty

For anyone following this, I’m slowly building you up to a fully-featured sortable, filtered scaffold helper library.

You may recall we already built filtering with SELECT dropdowns. I’m going to add an input box and some sorting to that.

First, though, we need a little sumthin sumthin to simplify the UI: the twisty!

The twisty is the proper name for that little triangly ► which turns into a ▼ when you click it, revealing some more information (maybe a tree node, or more options).

We’re going to extend prototype’s Element object to create Element.twisty. It’ll all make sense later, I promise. First, here’s the functionality we’re heading for:

more info ►

explanation

The code simply toggles a hidden div, and depending on the visibility, changes the little arrow to match.

Things to look out for in this code: returns false, so you can return Element.twisty and it won’t jump to the top of the page; takes a string or a DOM node; uses unicode for the twisties; requires a SPAN element in your A.

<script type=’text/javascript’>
Object.extend(Element, {
twisty: function(element, _next) {
element = $(element); _next = $(_next);
var span = element.getElementsByTagName(‘SPAN’)[0];
span.innerHTML = (_next.style.display == ‘none’) ? ‘&#9660;’ : ‘&#9658;’
Element.toggle(_next);
return false;
}
});
</script>

<style type=’text/css’>
span.twisty { font-size: 70%; }
</style>

<div style=’width:200px;border:1px solid #ccc;’>
<a href=’#’ onclick=’return Element.twisty(this, $(“admin-info”));’>more info <span class=”twisty”>&#9658; </span></a>
<div id=’admin-info’ style=’display:none’>
Here’s your other box!
</div>
</div>

you know I can’t leave it alone

Why stop there?

Let’s set up a default box for the twisty to show/hide.. and while we’re at it, if the twisty <a> doesn’t have a SPAN in it, we’ll generate one automagically.

Object.extend(Element, {
twisty: function(element, _next) {
element = $(element);
var span = element.getElementsByTagName(‘SPAN’);

// automatically generate that SPAN if she doesn’t exist
if (span.length == 0) {
span = document.createElement(‘span’);
span.className = ‘twisty';
element.appendChild(span);
}
else span = span[0];

// use a default action to find the node to hide/show
if (!_next) _next = findParent(element, ‘li’).nextSibling;
span.innerHTML = (_next.style.display == ‘none’) ? ‘&#9660;’ : ‘&#9658;’
Element.toggle(_next);
return false;
}
});

<ul>
<li><a href=’#’ onclick=’return Element.twisty(this);’>Toggle</a></li>
<li style=’display:none’>This is your content box</li>
</ul>

This way, it will apply automatically to a UL by hiding or showing the next LI, unless you override _next. so <a onclick=’return Element.twisty(this)’ href=’#’ > will work. Of course you can modify this yourself.

(FYI, this example won’t quite work as published, you need to Element.cleanWhitespace the parent UL in firefox, but I’m trying to keep it simple)

OK, so we have a twisty

Let’s add sorting to our filterable table header. To keep the UI nice and simple, we’re going to hide the filter boxes and make the TH clickable for sorting.

<table>
<thead>
<tr>
<th><a href=’/controller/list?filter=<%=params[:filter] %>&amp;order=monkey’>monkey</a></th>
<th><a href=’/controller/list?filter=<%= params[:filter] %>&amp;order=’foo’>foo</a></th>
<th>Non-sortable</th>
<th><a href=’#’ onclick=’return Element.twisty(this,$(“filter-row”));’>filter <span class=’twisty’></a></th>
</tr>
<tr style=’display:none’ id=’filter-row’>
<th>
<form action=’list’>
<input type=’hidden’ name=’filter’ value=” />
<input type=’text’ name=’filter’>
<input type=’submit’ value=’&raquo;’ />
</form>
</th>
</tr>
</thead>
<tbody>
<tr><td>monkey one</td>
<td>something</td>
<td>sample data</td>
<td></td>
</tr>
</tbody>
</table>

hint: click ‘filter’

monkey foo Non-sortable filter ►
monkey one something sample data
monkey two somethin else jaket sux

You’re probably going to want some signifier of order (ascending, descending) so we’ll use the unicode characters ▲ and ▼

I’m going to make this one a helper method, so our code looks nicer.
def table_sorting_header(fieldname, options = { :default => false })
params[:order] ||= “#{fieldname} asc” if options[:default] == true
if params[:order] == “#{fieldname} asc”
“<a href=’/controller/list?filter=#{params[:filter]}&amp;order=#{fieldname}+desc’>#{fieldname}” +
“<small>&#9650;</small></a>”
elsif params[:order] == “#{fieldname} desc”
“<a href=’/controller/list?filter=#{params[:filter]}&amp;order=#{fieldname}+asc’>#{fieldname}” +
“<small>&#9660</small></a>”
else
“<a href=’/controller/list?filter=#{params[:filter]}&amp;order=#{fieldname}+asc’>#{fieldname}</a>”
end
end

Call it like <%= table_sorting_header ‘monkey’ %> or if you sort one of the columns by default, <%= table_sorting_header ‘id’, { :default => true } %> on that column.

There’s the view done.. hook it up!

Open up the controller and fire away.. You’ll need the revised Hash#to_sql that converts ‘%’ queries to ‘LIKE’.

def list
@order = params[:order].gsub(/^(\w)\s/, “LOWER ($1) “) if params[:order] =~ /^(monkey|foo|id) (asc|desc)$/
@conditions[:monkey] = “%#{params[:monkey]}%” } if params[:monkey]
@conditions[:foo] = “%#{params[:foo]}%” if params[:foo]
@monkey_pages, @monkeys = paginate :monkey, :per_page => 20, :order => @order, :conditions => @conditions.to_sql
end

Scaffolding on Crack

Do you have a massive list of items in a scaffold-type arrangement (e.g. in a typo-style admin)? Here’s a way to quickly and easily filter and sort your big-assed list.

Note: this requires the Hash#to_sql function posted here a few weeks ago .. told you it was useful!

More after the jump..

First, we’re going to tackle filtering; if y’all want sorting or ajax, too, please leave some comments to motivate me to write the second half. Just so I know you care :)

Like any good web coder (har, har) let’s start with the view. We have articles, they’re organized into simple categories (Category model), written by authors (Author.find(:all) is stored in @authors)

<table>
<thead>
<tr>
<th>Post title</th>
<th><select name=’main_category’ onchange=’filtering();’ id=’filter_category’>
<option value=”>Main Category</option>
<%= options_from_collection_for_select(Category.find(:all), ‘permalink’, ‘category_name’, params[:category].to_i)%>
</select></th>
<th>
<select name=’author’ onchange=’filtering();’ id=’filter_author’>
<option value=”>Author</option>
<%= options_from_collection_for_select(Author.find(:all), ‘id’, ‘nickname’, params[:author].to_i )%>
</select></th>
</tr>
</thead>

Now, that’s the header.. it looks something like this:

Post title   Main Category   Monkeys   Elephants   Author   Joe   Fred
The giant monkey returns Monkeys Joe
Who’s the biggest, grayest mofo? Elephants Fred

Finally, some pagination:

<div class=”pagination”>

<% @pagination_params = {
:category => params[:category],
:author   => params[:author],
:action   => :list,
:controller => ‘article’
}
-%>
<%= pagination_links(
@content_pages, :window_size => 15,
:link_to_current_page => false,
:params => @pagination_params
)%>

</div>

Now, you may notice there’s some javascript in those Select boxes: onchange=’filtering();’. Here’s that function.

<script type=’text/javascript’>
function filtering() {
var url = “/article/list/?filter”
var category = $(‘filter_category’);
var author = $(‘filter_author’);

if (category.selectedIndex > 0) url += ‘&category=’ + category.options[category.selectedIndex].value;
if (author.selectedIndex > 0)   url += ‘&author=’ + author.options[author.selectedIndex].value;
window.location.href = url;
}
</script>

Hopefully that’s fairly self-explanatory; it builds a query string from the values of the two select boxes. Next: onto the controller.

class ArticleController < ApplicationController
def list
# create a conditions hash from our params, if they exist
@conditions[:main_category_id] = Category.find_by_permalink(params[:category]).id if params[:category] and !params[:category].empty?
@conditions[:user_id] = params[:author] if params[:author] and !params[:author].empty?

@content_pages = Paginator.new self, Article.count, 10, @params['page'].to_i
@contents = Article.find(:all, :conditions => @conditions.to_sql, :order => ‘published_at desc’, :offset => @params['page'].to_i, :limit => 10)

@authors = Author.find_by_sql(“SELECT DISTINCT(content.user_id), users.* FROM #{Article.table_name} LEFT JOIN users ON content.user_id = users.id WHERE content.type = ‘Article’ ORDER BY users.nickname ASC”)
# this is our fairly specific sql, yours is probably much different.

@categories = Category.find(:all)
@authors = Author.find(:all)
end

end

Voila! We now have dropdown filtering.

The 3 Coolest Ruby on Rails Projects

As you know, I’m a bit of a fiend for all things Ruby on Rails. I love the language, and how incredibly versatile it is. It’s such a powerful tool, and today I want to showcase to you some of the amazing things people all around the world are using it for.

First up is the very cool Tennis Hub. The founder, Eddie Ross, is a super smart guy who has been in the start-up scene for a while now. He is also an avid tennis player, and saw a whole in the market.

Tennis players were only playing a fraction of the amount they wanted to play, simply because they couldn’t find other people to play with often enough. Tennis coaches had plenty of sessions they wanted to full, and tennis clubs were operating well below their capacity.

So with a team of Ruby developers, he went about creating a platform that would connect tennis players with other enthusiasts, with coaches and clubs, so that everyone in the tennis community would see an upturn in their involvement, and for coaches and clubs, in their profitability.

You can think of Tennis Hub as a platform like Tindr. Someoen posts availability in your area, you click to say you’re in, and it’s a done deal. They only charge coaches and clubs $2 per booking, but it can add a tonne of revenue to their annual P&L sheet.

I love a good game of tennis myself, so I’m thrilled for Tennis Hub to keep expanding until it gets to my area and I can start taking advantage of it.

Next up is SupaDupa. It’s basically a ‘plug and play’ platform for boutique stores. It comes with customisable themes and templates, and frees small creative businesses to really take their store to the next level.

Since a few of my friends are the fashion-y types, this makes me really excited. There’s finally a crossover in our interests! It’s got a really great UI, making it so simple for even the most technophobic types to create an amazing ecommerce platform.

Finally, comes RiskMNGT, an incredibly powerful tool for businesses in high-risk niches, particularly in software and development. RiskMNGT essentially allows you to predict and manage risk according to a pre-determined set of parameters.

You can track and manage everything from impact, to probability, to exposure level, as well as developing mitigation and contingency plans. It’s pretty damn impressive and will be saving a lot of heads from a lot of chopping blocks.

The Best Music To Code To

I don’t know about you, but the music I rock out to while I’m programming has a big impact on how I work.

If I’m listening to heavy, hard rock stuff, I find myself banging the keys on my (already battered) keyboard way too hard, feeling unstoppable but actually making a lot more mistakes than I should be.

If I go with trippy stuff, like Phish or MGMT, I float along, feeling zen, just flowing with the work at a comfortable pace, with only an occasional mental glitch.

Sometimes I’ll get nostalgic and whack on some Fall Out Boy, or Dashboard Confessional. The old familiarity just gets me in the zone instantly and I’m on fire for as long as the album lasts.

Other days it’s a dubstep kinda feel, and I find myself wriggling around my seat a lot more than I would usually. Those days I feel super energised about my code and I go to bed really satisfied.

Unfortunately, since every day is different and brings different challenges, I can’t just settle on one style to go with every day.

For this reason, I’ve created huge playlists that move me through each day, regardless of how I’m feeling or how the programming is coming. I made them carefully, intentionally listing tracks to move them naturally from one genre to another so I can get in a flow and not be distracted by a jump from dubstep to quiet classical.

This came up amongst some friends the other night and it was awesome hearing about bands and artists they are listening to. It gave me heaps of new material, so I encourage you to get out there are find some fresh stuff too!

 

Health Tips For Programmers

Let’s face it. Ever since you started coding, your body has taken an unmistakable turn for the worse.

Your skin has lightened to the point of being reflective, your diet now consists of crisps and cookies, and let’s not even talk about the disaster zone that is your posture.

Actually, let’s.

Your spine. You are ruining it. And you might not have noticed lately, what with all the non-movement, but you need your spine for a few things. You know, walking, standing, not being a cripple.

So here’s what you’re going to do.

Set yourself an alarm, every hour on the hour throughout your workday. Every time that alarm goes off, you are going to stand up and walk away from your desk. You’re going to swing your arms around and bend over a few times. You’re going to roll your shoulders back and forth, and make sure that you’re standing straight.

You’re also going to go to Massage World, and order yourself a basic table. When it arrives, you’re going to get a recommendation for a reputable massage therapist, and set up a monthly appointment with them where they will come and annihilate all the knots in your muscles and straighten out your skeletal alignment.

Finally, you’re going to stop drinking all that corrosive rubbish that burns your stomach and rots your teeth and replace it with water. Yes, water. I know you rely on your sodas for energy but you will die an early and unpleasant death if you don’t get this in hand.

Got it? Good. Get to it.

How To Have A Social Life If You’re A Coder

Ah, code. For most of us who work with you, you are an infuriating, impossible, irresistible lover we just can’t get enough of.

You keep us up at night. You keep us in at home when we know we should be out. Time and again we choose you over older, less demanding friends.

So it’s little surprise when, a few years into the relationship, we claw our way up to air to find our social lives in tatters.

Today it’s time to find a little balance in the relationship.

First things first. Your friends. You should contact them. You might have to remind them who you are, and how you know them. Once that’s taken care of, you should invite them to meet up with you for a few quiet drinks.

You don’t want to overwhelm them by excitedly announcing that you’re going to have a rager. Plus, you haven’t been out in ages. You can’t handle a rager, so don’t put it on the table.

Once that’s done, set yourself reminders. This ain’t gonna be easy. You need to be strict here. Set reminders on your phone and computer 40 minutes and 30 minutes before you need to leave.

That way, you have time to finish off that string you’re working on, or at least scribble down where you’re at with at, as well as leaving time for a shower and a sprucing. No, seriously. You need to shower. You look terrible, dude, you can’t go out like that.

Finally, get to the venue and stay there for as much beer and banter as you can manage. Preferably a bit more. Be interested in your friends, and do not for the love of God tell them about the problematic jQuery you’re dealing with right now.

Just relax into it. Have some fun. Remember why people are just as good company as your computer, and try to organise the next time you’re going to do this, too.

A Brief Introduction to Ruby On Rails

Ruby on Rails is the new kid on the block when it comes to programming. The other languages – PHP, Perl, Java and so on have been around for many years. Ruby’s only about 5 years old, having been extracted from Basecamp’s sophisticated programming by David Heinemeier Hansson.

Now, while other folks refer to it as Rails, around here, things go Ruby’s way, so don’t go getting confused if you hear someone else calling it differently.

Ruby is built on a pattern based on models, views and controllers.

The models are the part of the app that hold all the data. They describe the problem the app is trying to fix, as well as giving the app a structure to do that in.

The views are appearance templates that render data so the user can work with them, as well as managing all the visual and representational logic in the app.

Finally, the controller is the man in the middle, processing requests from users at the view point through to the model in the back end. It controls the flow of information and process in both directions of the app.

When Heinemeier Hansson extracted this programming methodology, he did it with a view to increasing programmer productivity – not app performance. This means it’s really not everyone’s cup of tea… meaning that the number crunchers don’t love it because it’s not necessarily going to give them the quickest return, but programmers and devs love it because it’s so much better to work in than the older, clunkier languages.

Yes, it’s a bit slower than those titans, but it’s getting faster and faster with every iteration and I think the programming community is only going to grow to love it more and more.

What Is HABTM?

Real talk. HABTM means HasAndBelongsToMany, but it’s one of those confusing acronyms that doesn’t really match what it stands for.

See, when you Wiki it, the page that comes up is Many-To-Many. Which is fine, it makes sense, but it’s not matching. I kinda like when things match, ya know?

When you’ve been programming a while, you get used to hacking together HABTM or many-to-many commands. These two rays of sunshine are basically a way of modelling data, or showing a correlation between database tables.

Database tables are built around cardinality, which is essentially a very precise description of why those tables should be linked, and the logic that keeps them linking together accurately.

Now, many-to-many tabling is pretty fancy, but to to make it work you also need to understand one-to-many tabling. To stick with the excellent example given in Wikipedia on cardinality (this table association):

A hospital database might contain 3 different ‘tables’ or data sets that need to be linked together: the table of doctors working there, the patients being treated, and the departments that make up the hospital.

In a one-to-many situation, the doctors and departments might be linked, as each doctor would only operate in one department (so for example, you’re not going to find the oncologists showing up in the pediatrics table).

But in a many-to-many situation, you might find the crossover between multiple patients being treated by multiple doctors – and sometimes even in multiple departments.

This crossover is where understanding HABTM really counts. You can’t be having these table interactions get messed up or the database is going to spit out completely screwy data. Getting familiar with HABTM takes time but it’s worth putting in the effort to get it right, because it’s going to open many, many doors for you. Get your tabling accurate and you’ve got a multitude more projects you can work on.