Forum posting sometimes pays off

Promotion 2 Comments »

Advertising on a teeny budget usually means doing a lot of legwork and posting site material in a lot of places. In many cases, you’re bordering on spam, which is kind of depressing. Plus, it can seem that no matter how much you write, no one ever reads it or follows the links to your site. There is no secret to it, but you just have to keep trying.

Recently, I found TreasureTables, a blog for tabletop RPG Game Masters (GM). In the forums, there is a section devoted to GM resources. Since Obsidian Portal is definitely a resource for GM’s, I went ahead and put up the pitch statement, along with a call for feedback.

Within a day, there were two new campaigns signed up (Dark Skies and Shadows of Skullport), and several people had posted specific, useful feedback regarding the site. Some had even commented on the possible commercial aspect of the site and how much they would pay to use it. Of course, that has to be taken with a grain of salt because it’s much easier to say you’ll pay than it is to actually drop the money.

From the 20 minutes to create the forum posting, and the probably 1-1.5 hours since then updating it as people ask questions, I have been able to generate 2 campaigns and probably 5-6 signups. That may seem small, but for a small site trying to grow, that’s a big deal.

The moral of the story is to keep hammering away at blog comments, forums, and the like. I have learned that “word of mouth” advertising often means your words, your mouth. It can seem frustrating, constantly searching for new places to regurgitate the same pitch over and over, but it is necessary at this stage. Keep marching on and eventually someone will bite.

acts_as_fedora – A Rails plugin for the Fedora content repository

Plugins, Ruby on Rails 1 Comment »

The Background

At work I’ve been diving into the Fedora content repository system. Totally unrelated to the Linux distro of the same name, the Fedora repository is a really cool database on steroids for all sorts of heterogeneous content. Text, media, files, and metadata can all be easily associated with one another in a single package.

Unfortunately, getting the data in and out of a Fedora instance can be tricky. The interface is via SOAP calls, which while not incredibly hard, are not all that easy either. Further, the Fedora development team has a propensity for changing interfaces at an alarming rate. Being a sort of fast-and-loose developer myself, I can understand this, but it’s still a little frustrating.

When I first started playing around with Fedora, it took me about two days to finally get my Rails app to a point where I could ingest (add) and disseminate (retrieve) records from Fedora. Obviously, two days to get up and running is not something to be proud of in the Rails community. However, during the exercise, I started to get a feel for how the system worked, and the seed of a Rails plugin was planted.

Fast forward about a month, and things are looking a lot better. I have a good deal more experience as a plugin user, plus I understand the Fedora interfaces and have successfully used them quite a bit. In the spirit of giving back to all the plugin authors that have helped me immensely, I am announcing my intent to create a plugin for Fedora.

Goals

The goals for acts_as_fedora are fairly modest, at least at this stage. It might get more features in the future, but for now I’m following the KISS principle.

  1. Easy to define a Fedora digital object (ie. datastreams) in a model object.
  2. Create a new digital object by instantiating a model, filling in data values, and calling save.
  3. Retrieve a digital object from the repository by its PID.
  4. Read a datastream as an accessor on the model object (like foo.DC for dublin core).
  5. XML datastreams are preloaded into REXML::Document objects for easy processing.
  6. Update a datastream by changing its value (via an accessor) and calling save.
  7. Purge an object.

Astute observers can probably see that I’m trying to get basic CRUD functionality with respect to datastreams. We can deal with disseminators later ;)

Schedule

I have already started coding and testing for acts_as_fedora, and I hope to have a working alpha version that satisfies the stated goals by the end of June. This post is just a kick in the pants to myself in order to get moving. If you’re reading this after June 2007 and there is still nothing for acts_as_fedora, please send me a work email at mwedeme @at@ emory edu and tell me to get moving!

Use whiny_finder and RecordNotFound to turn 500 into 404

Plugins, Ruby on Rails 12 Comments »

What happens when you can’t find the record the user is looking for? Let’s say the user is looking for blog post 9999, and you’ve only got 25 posts. What should happen? Not being an expert in HTTP, I’m not really sure, but returning a 404 in this case seems like a good idea. By default, Rails is set up to translate an unhandled ActiveRecord::RecordNotFound exception into a 404 response to the client (see update below). This is just another one of the nice little hand-holding defaults that makes Rails so friendly to noobs like myself.

To support this, the default find() method is designed to throw a RecordNotFound exception any time you request a record ID that does not exist. So, find(9999) in our example will throw the RecordNotFound exception, and assuming you’re not handling it explicitly, Rails will return a 404 to the client browser. In addition, the 404.html file in your public/web directory will be served out to the client. You can put all sorts of clever hints in here to guide the user to the right spot.

Unfortunately, not all find() methods are created equal. Only the most basic find actually throws the error. This is the find where you pass in the exact ID (or a list of IDs). With other incarnations of the find method, nil is returned but no RecordNotFound is thrown. If you’re using find_by_firstname_and_lastname all over the place, you’ll never get any exceptions. If you’re good, then you’re checking to make sure the return is not nil. If you’re sloppy (like me) you don’t do any checking and tell yourself you’re too busy.

The end result is that you get a nil back and then pass it to your views. At some point, you try to access a property and you get an “undefined method XXXX for nil:NilClass” exception. Unlike the RecordNotFound, however, Rails will return a 500 for this exception. A 500 indicates an internal server error, rather than a page not found. In other words, you’re admitting to the client, “I write sloppy code and something went wrong.”

One solution to the problem is to check every time you call find. If nil is returned, then raise a RecordNotFound exception. This will translate to a 404 and everyone is happy. “But I’m lazy,” you complain. “Bounds checking is just so boring.” Lucky for you (and me) someone else is just as lazy, but a lot more clever. They had the same idea and decided to code this behavior as a plugin, thus allowing the rest of us to DRY out our controllers.

The whiny_finder plugin is a simple and elegant bit of code that adds a “find!” (bang) complement to all your model classes. Following the standard Ruby convention, using the bang version of the method behaves exactly as the original, except when nothing is found a RecordNotFound exception is thrown. Where before we only had find_by_firstname_and_lastname, we now also have find_by_firstname_and_lastname! That last exclamation point makes all the difference.

To get the whiny_finder plugin, just run the standard plugin installer:

script/install http://soen.ca/svn/projects/rails/plugins/whiny_finder/

At that point, just take a couple minutes and do a search for “find_by_” and “find(:first” In a jiffy you can replace all your regular silent finders with their whiny counterparts. Then you’re set!

By installing a single plugin and spending 10 minutes updating your finders, you can turn tons of 500 “server error” into 404 “page not found” Your users (and friendly robots) will be better informed as to what’s going on, and your sloppy programming skills will once again be safely hidden away. What do you have to lose?

Update: Thanks to Tony in the comments, I have been informed that Rails 1.2.3 is not set up to respond with 404 on an unhandled RecordNotFound exception. This seems to have been added in Edge Rails, however.

It was working for me because I’m using the most up-to-date version of the exception_notification plugin, which seems to have been updated to match Edge Rails. I’m still using 1.2.3 for Rails, but getting exception_notification gave me the updated exception handling.

So, to get the 404s from unhandled RecordNotFound exceptions, you need to do one of the following:

  • Get Edge Rails
  • Get exception_notification (** what I would recommend **)
  • Override rescue_action_in_public in your application.rb controller.

BarCamp San Diego Recap

BarCamp, Ruby on Rails 1 Comment »

BarCamp San Diego (barcampsd) is finally over. It was awesome! I still haven’t caught up on my sleep. There were so many great presentations. Unfortunately being an organizer of the event I missed quite a few of them. We’re currently working on encoding the audio that was recording as well as syncing it with the video and encoding the video and we hope to have it up on the BarCamp San Diego Wiki this week. Planning for BarCamp San Diego 2 has already begun.

I gave essentially two presentations in one. I’ve uploaded the slides here so you can view them both. Up and Running with Ruby on Rails on Windows and Building an Ajax CSS Star Rating System using Ruby on Rails.

My Presentations
PDF IconUp and Running with Ruby on Rails on Windows
PDF IconBuilding an Ajax CSS Star Rating System using Ruby on Rails

What to know what you missed out on?

http://www.flickr.com/search/?q=barcampsd&w=all

http://www.technorati.com/posts/tag/barcampsd

Here’s a few of pictures for you:

Opening Session
Opening Session

Alex’s Presentation on Beyond Tag Clouds
Alex's Presentation on Beyond Tag Clouds

Make your own BarCamp San Diego T-Shirts
Make your own BarCamp San Diego T-Shirts

BarCamp T-Shirts

My Presentation
My Presentation

Yes, there was actual camping (indoors) at BarCamp San Diego
Camping at BarCampSD

No Cup Required!
No Cup Required!

SimpleSidebar – If you have sidebars, you need this plugin.

Plugins, Ruby on Rails 12 Comments »

Why you need it

Like many other websites out there, Obsidian Portal arranges its content into multiple columns. We have the main content in the center column, and ancillary content in the right sidebar. It’s a fairly standard organization scheme and it works well for us.

Normally, this sort of organization is handled in Rails via the use of layouts. One layout may contain the sidebars for your homepage, another one holds the sidebars for the user’s profile page, and so on. In the beginning, this works.

However, once your application reaches a certain level of complexity, this approach begins to show its true inflexibility. In many cases, you will have some sidebars that are common to every page, such as a login or search bar. You can split these into a partial, but you still have to include that partial in every layout. Not a big deal, but frustrating. Soon after this, you’ll run into cases where you need different sidebars based on the particular action for a controller. Perhaps there are some standard info sidebars for showing and listing, but for editing and creating you want a sidebar that has some editing tips. Now, if you’ve been using the convention for layouts, you probably have a layout for each controller that is named the same as the controller. That way, Rails will automatically select that layout. To support the different sidebars for different actions, you’ll have to clutter that layout up complicated if/then conditionals. Very quickly the template contains more Ruby than HTML.

Trust me, we went this route initially, and it became a nightmare. Here is one of our layouts, prior to SimpleSidebar:

< %= render :partial => “layouts/header” %>

< %= render :partial => ‘account/login’ -%>

< % if controller.action_name == 'show' %>

Description< % if session[:user] && permit?("game_master of :campaign") %> (< %= link_to 'Edit', {:action => ‘edit’, :id => @campaign._id} %>)< % end %>
< %=h @campaign.description %>

Party< % if session[:user] && permit?("game_master of :campaign") %> (< %= link_to 'Edit', {:action => ‘edit_members’, :id => @campaign._id} %>)< % end %>

GM: < %= link_to @campaign.game_master.login.capitalize, :controller => “account”, :action => “profile”, :login => @campaign.game_master.login %>

    < % players_with_pcs = [] %>
    < % for pc in @campaign.player_characters %>

  • < %=h pc.author.login %> (
    < %= link_to h(pc.name), :controller => ‘game_contents’, :action => ‘show’, :id => pc._id %>
    )
    < % players_with_pcs << pc.author %>
  • < % end %>
    < % for player in @campaign.players %>
    < % if !players_with_pcs.include?(player) %>

  • < %=h player.login %>
  • < % end %>
    < % end %>


< % end %>

< % if (controller.action_name == 'list') or (controller.action_name == 'search') %>
< %= render(:partial => ‘search/search_bar’, :locals => {:search_type => ‘Campaigns’, :search_controller => ‘campaigns’, :search_action => ‘search’}) %>

< % end %>

< % if flash[:error] %>
< %= flash[:error] %>

< % end %>
< % if flash[:warning] %>

< %= flash[:warning] %>

< % end %>
< % if flash[:notice] %>

< %= flash[:notice] %>

< % end %>
< %= yield %>

< %= render :partial => “layouts/footer” %>

Ignoring the fact that I’m terrible at writing templates, you can see there’s a fair amount of if/then conditional code sprinkled in. The Login sidebar is supposed to be there always, the Description and Party sidebars are only supposed to appear in the show action, and the Search bar is only supposed to be there in the list or search action. Ugh! And, this is only one of several layouts for several controllers. Each one had this sort of conditional garbage all over the place.

With SimpleSidebar, much of this conditional code moves into your controllers. Much like before and after filters, you define sidebars for a controller (or a particular action) and can give conditions on when they appear.

For example, using the previous example, with SimpleSidebar, I added the following to my controller:

sidebar :login, :unless => :logged_in?
sidebar :welcome, :if => :logged_in?

sidebar :campaign_description, :o nly => :show
sidebar :campaign_party_info, :o nly => :show
sidebar :campaign_search, :o nly => [:list, :search]

This allowed me to reduce my layout to the following:

< %= render :partial => “layouts/header” %>

< %= render_sidebars %>

< % if flash[:error] %>
< %= flash[:error] %>

< % end %>
< % if flash[:warning] %>

< %= flash[:warning] %>

< % end %>
< % if flash[:notice] %>

< %= flash[:notice] %>

< % end %>
< %= yield %>

< %= render :partial => “layouts/footer” %>

A little nicer, huh? If you look closely, there is nothing in there specific to any particular controller or action. Once I converted all my controllers over to SimpleSidebar, I noticed that all my layouts were identical, meaning I was able to delete most of them and just keep a single standard layout.

How to use it

SimpleSidebar is incredibly easy. I was up and running in about ten minutes (including the vendor drop). I was finished refactoring all my ugly templates in about 1.5 hours. Not bad for a major refactor.

Note: These instructions are for revision 13 of the plugin. Beware if you’re using a different version (although it probably won’t change that much).

1. Get the plugin

As always, it’s very easy to install plugins. Just fire up your plugin installer

script/plugin install svn://rubyforge.org/var/svn/simplesidebar

Likewise, as always, we here at AisleTen suggest you skip the plugin installer and do it manually using vendor drops. Just be sure to execute the install.rb when you’re done.

2. Update your controllers

This is where most of the magic of SimpleSidebar occurs. Rather than dealing with sidebars and their conditional display in the view layer, SimpleSidebar moves it to the controller layer. For example, your controller might look like this:

def MyController < ApplicationController
sidebar :login, :unless => :logged_in?
sidebar :welcome, :if => :logged_in?
sidebar :search
sidebar :edit_help, :o nly => [:edit, :new]


end

If you’re familiar with filters, then this probably looks very familiar. When an action is executed in this controller, the following will be run:

  1. If the logged_in? method returns false, then the login sidebar is appended to the list of sidebars to display.
  2. If the logged_in? method returns true, then the welcome sidebar is appended to the list of sidebars to display.
  3. The search sidebar is appended to the list of sidebars to display.
  4. If the current action is edit or new, then the edit_help sidebar is appended to the list of sidebars to display.

3. Add the partials.

If you’ve been good, you already have all your sidebars as partials. If not, it’s time to refactor as such. The partials need to be named the same as the sidebars listed in your controllers. Using our previous example, we will need four partials:

  • _login.rhtml
  • _welcome.rhtml
  • _search.rhtml
  • _edit_help.rhtml

These partials must be placed in the app/views/sidebars directory.

4. Update your layout.

Inside your layout, the code becomes very simple. All you have to do is add <%= render_sidebars %> wherever you want the sidebars displayed.

I highly recommend extracting this to your layouts. That way, rather than calling render_sidebars in each template you render, you just put it into the layout and know it gets called every time the layout is rendered around your template.

5. Delete all the layouts no longer needed.

Assuming you’re like me, you’ll quickly find that many of your layouts are no longer needed. Feel free to consolidate them as appropriate.

Advanced Features

SimpleSidebar also contains some advanced features that I have yet to experiment with, but I’ll still give a quick overview.

Components

If I understand it correctly, components are sidebars that also have an associated controller. This is a very exciting feature, as it could allow you to execute multiple controllers for a single request.

A good example of where this is appropriate is for dynamic sidebars, such as the “Recently Updated Campaigns” sidebar you see on the Obsidian Portal homepage. I need to execute a database query (find) in order to get this. Currently, I’m just doing it inside the partial, which is not really what you’re supposed to do. When I get a chance, I’ll see if I can refactor this and use a component to move the database querying into a controller and make the partial a dumb template.

Sidebar ordering and sorting

In the previous examples, sidebars were ordered simply by their place in the controller. However, if you need more advanced functionality, SimpleSidebar supports ordering and sorting.

Moving sidebars is accomplished like this:

sidebar_move :login, :top
sidebar_move :search, :bottom
sidebar_move :search, :up
sidebar_move :login, :down

Easy enough…

Sorting looks a little more complicated. If I figure it out (or ever have a need for it), then I’ll update how it’s done. Until then, just look in the plugin source for sidebar_sort.

Issues

The only issue I can raise against SimpleSidebar (and it’s a long shot) is that by design it mixes controller and view functionality. I think sidebars are an aspect of the view, but with SimpleSidebar you deal with them in the controller.

In all seriousness, though, this is like whining over the color of the inside of the glove box in a luxury car. In no way does it take away from the sheer awesomeness of the item in question.

Final thoughts

After my brief introduction, I am completely in love with SimpleSidebar. It has quickly made its way into my bag of permanent plugins for all Rails projects. In any future project, it will be the one I install right after acts_as_authenticated. Yes, it’s that awesome.

Tomorrow is BarCamp San Diego

BarCamp, Projects 1 Comment »

Tomorrow is Barcamp San Diego! It’s taken about a months worth of planning to get ready for tomorrow’s event and thanks to sponsors that we’ve lined out it’s going to be awesome.

BarCamp San Diego Logo

We’ve had almost 70+ people sign up so far and we’re expecting around 100+ people to show. Not to mention it’s been brought to my attention that we’ve been listed on Boing Boing as you can see below:

BarCamp San Diego on BoingBoing

BarCamp is an ad-hoc gathering born from the desire for people to share and learn in an open environment. It is an intense event with discussions, demos, and interaction from participants. The name BarCamp was inspired as a complement to FooCamp. FooCamp is the annual invitation only, no-structure, no plan, tent on the lawns, hacker event hosted by publisher Tim O’Reilly.

Two videos capture the essence of BarCamp. Take a look at video summaries from BarCamp SF and BarCamp Austin

Let the partying begin!

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in