The last few tutorials have got us pretty far with the “Gabber” application–we’ve now got a micro-blog up and running allowing you to create new posts (using Ajax no less!) and view them in reverse order as part of a styled page.
What we’re going to do now is add some extra bits for choosing avatars when posting messages and the ability to comment on posts too.
Remember, you can view the final application at http://gabber.d13design.co.uk/gabber/public/posts.
We’ll be adding in a few extra images for the avatars so, if you don’t want to create your own, you can download the ones I used here.
Download Gabber files
Adding some avatars
Okay, let’s get started. First we’ll update our database to store an avatar against each post. Open up the migrate file in the db folder (”db/001_create_posts.rb” or something like that) and we’ll add in an extra column:
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.string :title
t.string :poster
t.string :avatar
t.timestamps
end
end
def self.down
drop_table :posts
end
end
Now we need to update the database. Unfortunatley, the only way I’ve found to do this requires a database reset so all of my previous posts have been erased. Using a rails console, run the command:
rake db:migrate:reset
This should give you an output similar to:
== 1 CreatePosts: migrating ============================= -- create_table(:posts) -> 0.0940s == 1 CreatePosts: migrated (0.0940s) ====================
Great, that’s set our database up to hold avatar data for each post. Now we need to add the avatars to the “create” form. Open your “index” view and add the following code somewhere within your form tags:
<table>
<tr>
<td><%= image_tag 'avatar_.gif' %></td>
<td><%= image_tag 'avatar_1.gif' %></td>
<td><%= image_tag 'avatar_2.gif' %></td>
<td><%= image_tag 'avatar_3.gif' %></td>
<td><%= image_tag 'avatar_4.gif' %></td>
<td><%= image_tag 'avatar_5.gif' %></td>
<td><%= image_tag 'avatar_6.gif' %></td>
<td><%= image_tag 'avatar_7.gif' %></td>
</tr>
<tr>
<td><%= radio_button :post, :avatar, '' %></td>
<td><%= radio_button :post, :avatar, '1' %></td>
<td><%= radio_button :post, :avatar, '2' %></td>
<td><%= radio_button :post, :avatar, '3' %></td>
<td><%= radio_button :post, :avatar, '4' %></td>
<td><%= radio_button :post, :avatar, '5' %></td>
<td><%= radio_button :post, :avatar, '6' %></td>
<td><%= radio_button :post, :avatar, '7' %></td>
</tr>
</table>
If you save your files and run your application you’ll get a screen a bit like this.

Before you add a new post to try out your new additions we’ll something into the index view to display which avatar was selected.
<div class="post"> <p><strong><%=h post.poster %> says</strong> “<%=h post.title %>”</p> <p>Avatar: <%=h post.avatar %></p> <p class="postmeta">posted <%=h post.created_at %></p> </div> <div class="clear"> </div>
Save your view file, run your application and add a post.

Now we can edit the markup and styles to make sure we use the correct post background image to reflect the avatar that was chosen. Adjust your stylesheet removing the background image from the post div:
div.post {
background-color:#ff9;
background-position:top left;
background-repeat:no-repeat;
padding:0px;
margin:0px;
height:100px;
}
And adjust your index view file to add the following:
<div class="post" style="background-image:url(stylesheets/post_bg_<%=h post.avatar %>.gif);">
When you’re happy that it’s all working, remove the text we added to display the avatars and you should have something like this:

Letting people comment
The first thing we need to do is set up comments as a model, in the same way that we set up posts. To do this, open a Rails shell/console and type the following:
script/generate model comment
This will run through the generate script and create our model. We now need to think about the properties of a comment on our blog:
- A comment will belong to a post
- A post may have many comments
- A comment will have a title
- A comment will have a message
- A comment will have an avatar
Bearing all of this in mind we can make some changes to the comment model, the post model and the newly created database migration file. By editing the comment model (app/models/comment.rb) we can tell it that a comment belongs to a post:
class Comment < ActiveRecord::Base belongs_to :post end
By editing the post model (app/models/post.rb) we can tell it that it may have many comments belonging to it:
class Post < ActiveRecord::Base has_many :comments end
And finally we’ll edit our new database migration file to tell it how to structure our comments in the database. Edit the file in your “db/migrate” folder (002_create_comments.rb) and set the table up in the same way we set our posts table up:
class CreateComments < ActiveRecord::Migration
def self.up
create_table :comments do |t|
t.integer :post_id
t.string :title
t.string :poster
t.string :avatar
t.timestamps
end
end
def self.down
drop_table :comments
end
end
Now we’re ready to run the migration–your comments will now be set up.
What we need to do now is provide a way for people to actually add comments, we’ll do this by editing some of the view files. Open your layout and edit it so that the main “Gabber” title is a link back to the main home page:
<div id="header"> <h1><%= link_to 'Gabber', posts_path %></h1> <h2>A collaborative micro-blog</h2> </div>
Next we’ll edit the main index view to add a “comments” link:
<%= link_to 'comments', post %>
If you run your application you’ll now be able to click on the comments link and view a post but it won’t be styled. Edit the “show” view file and apply the markup from your index page–making sure not to destroy the Rails code–and you should have something like this.

We’ll now add a form to attach comments to a post, list all existing comments and we’ll remove the links that we no longer need. Edit your “show” view:
<div class="post" style="background-image:url(../stylesheets/post_bg_<%=h @post.avatar %>.gif);">
<p><strong><%=h @post.poster %> says</strong> “<%=h @post.title %>”</p>
<p class="postmeta">posted <%=h @post.created_at %></p>
</div>
<div class="clear"> </div>
<hr/>
<% for comment in @post.comments.reverse %>
<%= comment.title %><br/>
<%= comment.poster %><br/>
<%= comment.avatar %><br/><hr/>
<% end %>
<div id="newpostform">
<h3>Comment on this post</h3>
<%= form_tag :action => "comment", :id => @post %>
<p><b>Your message</b> <%= text_field_tag 'comment[title]' %></p>
<p><b>Your name</b> <%= text_field_tag 'comment[poster]' %></p>
<table>
<tr>
<td><%= image_tag 'avatar_.gif' %></td>
<td><%= image_tag 'avatar_1.gif' %></td>
<td><%= image_tag 'avatar_2.gif' %></td>
<td><%= image_tag 'avatar_3.gif' %></td>
<td><%= image_tag 'avatar_4.gif' %></td>
<td><%= image_tag 'avatar_5.gif' %></td>
<td><%= image_tag 'avatar_6.gif' %></td>
<td><%= image_tag 'avatar_7.gif' %></td>
</tr>
<tr>
<td><%= radio_button :comment, :avatar, '' %></td>
<td><%= radio_button :comment, :avatar, '1' %></td>
<td><%= radio_button :comment, :avatar, '2' %></td>
<td><%= radio_button :comment, :avatar, '3' %></td>
<td><%= radio_button :comment, :avatar, '4' %></td>
<td><%= radio_button :comment, :avatar, '5' %></td>
<td><%= radio_button :comment, :avatar, '6' %></td>
<td><%= radio_button :comment, :avatar, '7' %></td>
</tr>
</table>
<p><%= submit_tag 'Post comment' %></p>
</form>
</div>
Refresh your page and you should see a new comment form when you view a post. Trying to submit a comment will error though–we haven’t written how to handle comment submissions!

Open your posts controller and we’ll define what to do when a new comment is submitted. Just under where the index is defined add the following:
def comment
Post.find(params[:id]).comments.create(params[:comment])
redirect_to :action => "show", :id => params[:id]
end
You should now have, among other things in this file:
def index
@post = Post.new
@posts = Post.find(:all).reverse
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @posts }
end
end
def comment
Post.find(params[:id]).comments.create(params[:comment])
redirect_to :action => "show", :id => params[:id]
end
Give it a try now and you should get something like this:

If we edit the markup and stylesheets further we can get something like this:

Finally, we’ll adjust the way posts are displayed on the index view to tell us how many comments they have. we can do this by adjusting adding the following within the markup for displaying a post:
<%= post.comments.count %> comment(s)
Your homepage should now look a little like this:

And that’s it. Your micro-blog is up and running ready for all to use!