The Big Rewrite is Here

When I first started this blog, it was my very first Rails project. I was young. I was naive. I didn't do automated testing.

Fast forward back to September, and I wanted to start adding some new features. I wanted to do it right though, with tests, and all. To my dismay, I found the way I had implemented things weren't so easy to test.

This, along with Rails 2.0 coming along, and some other new libraries/plugins I wanted to learn, led me to starting a complete rewrite.

So, here's a laundry list of what I've been using so far:

I think I'm mostly feature complete, but the most significant missing piece is...

Comments! I mostly need to find a good way of spam filtering. The original version was using simple_captcha, but I've been noticing spam has still been getting through. I'm considering trying akismet, which does have a few Rails plugins.

But yeah, that's it for now. I hope to pump out a few posts about this new stuff I'm using.

December 09, 2007 at 01:24 Permalink Edit Destroy

Adding a tag listing

My next move was to be able to have a page listing all the known tags in the system. I first refactored the tags action to by_tag, so that it reads a bit better, and so I could use tags action for my tag list action.

Here's what the new tags action looks like:

def tags
  @tags = BlogPost.tag_counts
end

This tags_counts is actually added to your model when you add acts_as_taggable to your model class. The name is a bit misleading, but it does provide you a list of tags for the given model. The Tag object also includes a count of how many things are using it, hence the name tag_counts. The acts_as_taggable homepage suggests this was intended to help you generate a tag cloud.

Here's what my rhtml looks like:

<h2>All known tags:</h2>
<ul>
  <% @tags.each do |tag| %>
    <li><%= link_to tag.name, {:controller => 'blog', :action => 'by_tag', :tag => tag.name} %></li>
  <% end %>
</ul>

And with that, I have a some nice tag listing action going on. In a future iteration, I hope to turn this into a tag cloud.

July 16, 2007 at 00:18 Permalink Edit Destroy

Fixing the routes for tags

After my first forray into tags, I felt like I needed to further refine and enhance my usage of them.

So we had this code chunk:

# in app/controllers/blog_controller.rb
def tags
  # FIXME do routing magic to change :id to :tag
  @blog_posts = BlogPost.find_tagged_with params[:id]
  render :action => 'all'
end
...

# in config/routes.rb
map.connect 'blog/tags/:tag', :controller => 'blog', :action => 'tags'

The issue was that I wanted to be using params[:tag], not params[:id]. The cause was that my map.connect was declared AFTER the default connect string, ie:

# Install the default route as the lowest priority.
map.connect ':controller/:action/:id.:format'
map.connect ':controller/:action/:id'

Apparently I didn't read the comments closely enough :) Moving it above the default route, it works like I had hoped.

July 14, 2007 at 16:54 Permalink Edit Destroy

That's a lot of tags!!

With the help of actsas_taggableon_steroids I now have taggable blog posts!

It was really dead simple, just followed the instructions on their page.

What good is collecting tagging information if you don't display it, so of course, I want to add it to the partial used for the blog posts. I thought to myself, well, this is a list, so wouldn't it make sense to be a <ul>? Sure, but definitely not your typical <ul> with the bullets and all. I remember reading about using CSS trickery to make <ul>s look like comma separated list, and dug up something over here.

Here's the important snippet:

ul.links { list-style: none; margin: 0; padding: 0; }
ul.links li { display: inline; }
ul.links li:after { content: ","; } 
ul.links li:last-child:after { content: ""; }

I wanted it to be a bit more generic, so I called the class 'comma-separated'. I thought a little more about it, and realized I was doing pipe-separated lists without using <ul>. After some tweaking, I ended up with this CSS:

ul.comma-separated, ul.pipe-separated { list-style: none; margin: 0; padding: 0; }
ul.comma-separated li, ul.pipe-separated li { display: inline; }
ul.comma-separated li:last-child:after, ul.pipe-separated li:last-child:after { content: ""; }

ul.comma-separated li:after { content: ","; } 
ul.pipe-separated li:after { content: " | "; }

Here's the final code snippet I added to my _blog_post.rhtml partial:

<div class="post_tags">
  <ul class="comma-separated">
    <% blog_post.tag_list.names.each do |tag_name| %>
      <li><%= link_to tag_name, :action => 'tags', :id => tag_name %></li>
    <% end %>
  </ul>
</div>

As the code suggests, I also added a new action, for displaying all items matching a particular tag. It looks a little bit like:

def tags
  # FIXME do routing magic to change :id to :tag
  @blog_posts = BlogPost.find_tagged_with params[:id]
  render :action => 'all'
end

As the fixme points out, I really would like to be using :tag, since it's kinda abusing the meaning of :id. I tried hooking this up in my config/routes.rb, but it didn't quite hold up:

map.connect 'blog/tags/:tag', :controller => 'blog', :action => 'tags'

In any event, I'd say it works well enough for now, given how little time it took.

June 22, 2007 at 00:59 Permalink Edit Destroy