Tuesday, February 24, 2009

Getting the errorID from an ErrorEvent in ActionScript

Our Episodic Video Player is written in ActionScript 3. I'm still fairly new to ActionScript but came up with a solution to a problem the other day that I thought I should share.

The player loads various files from the server. In some cases I want to display an error when one of those files can't be found. I have an error handler that listens for Error Events and displays an appropriate error message depending on the type of the error event.  For example, I know that error code 2032 will generally mean in our case that the file could not be found. 

Alright, so this all seems simple enough except for one problem.  When I looked at the ASDocs for ErrorEvent.errorID I noticed that that property is not available for Flash Player 9.  Fortunately, ErrorEvent extends TextEvent which has text property I can access.  In the case of an ErrorEvent the text property contains a message that includes the error ID. Therefore, I just wrote my own getter to grab the error ID.

public function get errorID():int {
if ((text != null) && (text.indexOf("Error #") == 0)
&& (text.length > 7)) {
// The Error IDs always seem to be 4 digits
return parseInt(errorEvent.text.substr(7, errorEvent.text.length - 7));

Tuesday, February 17, 2009

Override attribute accessor and before_type_cast

Our Episodic Video Publishing Web Application is written in Ruby on Rails. I recently came across a situation where I had a model where I wanted to override it's attribute accessors in some cases. Consider a model that looks like this.

create_table "podcasts", :force => true do |t|
t.string "name"
t.boolean "use_show_name", :default => true
t.integer "show_id"

As you can see above that each podcast belongs to a show. I also have a form for this model and in the name field I want to display the name of the podcast unless "use_show_name" is true then I want to display the name of the show that this podcast belongs to.

<%= text_field :podcast, :name, :class => "text", :disabled => @podcast.use_show_name %>

I don't want to put this logic in the ERB template but instead I want to put it in the model so that anyone that calls Podcast.name will get the appropriate value depending on the "use_show_name".

class Podcast < ActiveRecord::Base
belongs_to :show
def name
return self.use_show_name ? self.show.name : read_attribute(:name)
alias_method :name_before_type_cast, :name

So there a few things going on above.

  • We override the "name" method by simply implementing it. This works because ActiveRecord using method_missing to implement it's "name" getter but since there is now a "name" method, method_missing will not be invoked.

  • In the method we check "use_show_name" to see what value to return.  If it is true we get the value from the show object.  Otherwise, we call read_attribute to get the value of the name attribute that stored in the DB.

  • Lastly, we alias the name method as "name_before_type_cast" since this is the method that is called by FormHelper.text_field.  ActiveRecord form helpers call the before_type_cast so that they can get the string value of the attribute but we want it to get the value from our "name" method.