exception_logger gem 0.1.8 supports jQuery

There’s an older but popular plugin called exception_logger that I’ve encountered in a few different Rails 2.x project. I found it a useful little tool for tracking uncaught exceptions in your production application, including views for managing them and supporting an RSS feed. The plugin fell into a state of disrepair and was showing signs of age. It would no longer run under Rails 3 due to changes to the way that exceptions are rendered in a production environment. As well, it used older Rails remote calls and prototype.js on it’s management page.

Enter Roland Guem (git user name QuBiT) who undertook the task of converting the plugin to a gem and made it Rails 3 compatible. The only issue left was that it meant you still had to include prototype support in your application. In an effort to try to contribute a little more to Open Source, I undertook my second project and converted the calls to unobstrusive jQuery. Needless to say, the code looks a lot cleaner and is easier to maintain going forward. With the release of the gem today (0.1.8), I’ve been able to upgrade a couple of production applications. I’m looking forward to tackling a little more in the Open Source domain as github really makes it a straight-forward process.

Advertisements

iCal support for Rails

I’ve been pretty busy this week making a ton of headway on a significant project. Said project has support for both events and contacts within it and it made a lot of sense to let users get these out seamlessly to other applications. I’ll write about the vCard support tomorrow and will focus on calendar support tonight.

I’d used the iCalendar gem before so it was only a matter of minutes to get it up and running with my application. In brief, here’s how I would suggest using it.

Add an ical method to the model that will be exporting events. You’ll need to require ‘icalendar’ in order to get access to that class within your model. Here’s an example of the mapping I did between my object and the Icalendar::Event.

def ical
  e=Icalendar::Event.new
  e.uid=self.uid    
  e.dtstart=DateTime.civil(self.date_start.year, self.date_start.month, self.date_start.day, self.date_start.hour, self.date_start.min)    
  e.dtend=DateTime.civil(self.date_end.year, self.date_end.month, self.date_end.day, self.date_end.hour, self.date_end.min)    
  e.summary=self.name    
  e.created=self.created_at    
  e.url=self.url    
  e.last_modified=self.updated_at    
  e   
end

Take notice of the UID field. You’ll want to ensure you have some sort of permanent UID identifying your event in the application so that subsequent exports (or RSS feeds) of the event will be updates.

You’ll want to handle the request to export the event in your controller. You could map it to the show method, but in my case, I added an export method.

def export
  @event=Event.where(:id => params[:id]).first
  respond_to do |format|
    format.ics
  end  
end

You’ll notice that the format is set to ics, the extension for a calendar file. You’ll need to make a modification to your config/initializers/mime_types.rb to add ICS support, like so:

Mime::Type.register_alias "text/calendar", :ics

Finally, in order to send the event to a calendar file, you’ll need add a view for the export method (in my case views/events/export.ics).

<% @calendar=Icalendar::Calendar.new %>
<% @calendar.add @event.ical %>
<% @calendar.publish %>
<%= @calendar.to_ical %>

That’s all there is to it – it’s really dead simple and should be an easy addition to any app. You can see how you might expand on this to share entire calendar feeds rather easily.

End before the start? validates_timeliness

It’s been a busy last few days working on a new project that has forced me to produce some of the best work (cleanest) work I’ve produced. Along the way, I’ve come across a few new gems that I’ve utilized to great effect. One of the things I love about Rails is that if you think of a problem, you can be assured it’s not unique to you. I was developing a model today that had a start and end date associated with it. Of course, I could written a custom validator to ensure to the end date was after the start date, but I realized I needed a few variation on this and decided to look for a gem. I found validates_timeliness, which fit the bill perfectly.

Installation and usage of the gem is as simple as advertised. In my case, I had some quick validations in place, such as:

validates_datetime :date_end, :after => :date_start, :if => :date_end

The gem provides a host of options, is Rails 3 ready and works on ActiveModel (meaning you aren’t restricted to ActiveRecord). I can see making good use of this in the future and wouldn’t be surprised if it made it’s way into Rails.

accepts_nested_attributes_for and _destroy without checkboxes

I’ve never been a fan of using check boxes on a form to mark child records for deletion. It seems a little counter-intuitive for most users. While I do use accepts_nested_attributes to mark items for deletion upon save, I don’t use checkboxes.

On my forms, I prefer to delete any list item or table rows that are to be destroyed (after prompting the user to confirm they want these deleted) and then figure out what needs to be deleted upon save. Take as an example Organizations that have many PhoneNumbers associated with them.

We update an organization object as follows:

@organization=Organization.where(:id => params[:id]).first    
@organization=params[:organization]

And then, before saving, perform the following for the nested attributes:

@organization.phone_numbers.each {|phone| phone.mark_for_destruction unless params[:organization][:phone_numbers_attributes] && params[:organization][:phone_numbers_attributes].detect {|k, v| v.detect {|fld, value| fld=="id" && value==phone.id.to_s}} }

This effectively marks for deletion any phone numbers which belong to the organization, but were no longer present on the form when submitted (because the user asked to remove them with confirmation). I find it makes for a cleaner interface. Two caveats to note in the inner detect call:

  1. Make sure you compare your ID field as a string because the params hash will represent the values as strings.
  2. You want to compare the field name to “id” and not :id as it is not a symbol in the incoming params hash, but a literal string.

jQuery HotKeys

Today was spent refactoring a lot of code on a soon to be released project and trying to optimize some data entry screens. It’s important to try to keep the user on the keyboard as much as possible with as few trips back to the mouse if it can be avoided. On the screen in question, they are often going to be adding a lot of new rows to a table. I had refined the data entry down to a pretty quick process but was left with the problem of having to click the “Add xxx” button to add a new row, a very disruptive process.

Enter jQuery HotKeys. This a pretty slick jQuery plugin that allows you to associate a keydown (or keyup etc) event for a given object with a function.

$(document).bind(‘keydown’, ‘ctrl+a includeInput’, function() {add_game(); return false;});

The version I’ve shown has a small modification to allow this happen even when inputs have focus (thanks to Phil Mickelson for that addition!). It added the final refinement I was looking for to allow for really quick data entry.

 

jQuery live()

I’ve been working with jQuery for a little while, but because I didn’t read the API from start to finish, I’ve managed to discover some little things along the way. In my Rails apps, I typically have links/button that invoke an Ajax call to the server to render a partial and add it into the DOM somewhere (such as adding an Address partial to a Contact form). Often, I would have some masked entry fields (using jQuery Masked Input) or date pickers or something else that needed to be adorned  with the appropriate JS. Typically I would write some Javascript at the end of the partial rendering that would call some functions to go and reapply the right bindings, such as $(‘.time_field’).mask(’99:99′) for all of the  inputs of class .time_field or adding click functions for links.

The problem I typically ran in to was that I was continually binding the same event handlers on top of already existing handlers every time the Ajax was invoked. In those cases, I had to unbind the event handlers before binding the new event handler which seemed like a lot of extra work for no good reason: $(‘.some_class’).unbind(‘click’).click( function… or $(‘.time_field’)unmask().mask(’99:99′).

That lead me to my discovery of the  live() handler. live() allows you to bind events for all objects matching a selector at the time of execution AND for any new items added to the DOM. This lead to further simplification of my code. No longer did I need to tack on a little JS function when returning my rendered partial to adorn the fields needing extra behaviours when live() would take care of that for me. I really wish I knew about that before.

Purpose of this blog…

I created this blog a few months ago with very little idea of what I might do with it. I wanted something worthwhile for others to read and as something useful for me to look back on. I stole the concept of blogging about what I learned each day. I maintain an internal wiki, but that’s really of no use to anyone else. Instead, it’s a lot more use for me to post the tidbits and things that I learn about at the end of each business day, with the aim of collecting a lot of that information that would otherwise float in the ether.