Navin Samuel

Archive for July, 2008|Monthly archive page

ActiveScaffold & STI (Single Table Inheritance)

In Technology, Tecnoquips on July 21, 2008 at 11:53 am

I had a tough time getting ActiveScaffold to work with STI.  As per the development roadmap for AS, this will be available only in version 1.3! Since I desperately needed this to work, I figured out a quick workaround. In the models, rename your foreign keys to the name of the derived class. That’s it! Below is an example.


# Base class
class Promotion < ActiveRecord::Base
end


# Derived class
class SurveyPromotion < Promotion
has_many :surveys,
:foreign_key => 'survey_promotion_id'
end


# Associated class
class Survey < ActiveRecord::Base
belongs_to :survey_promotion,
:foreign_key => 'survey_promotion_id'
end

ActiveScaffold @ REST

In Technology, Tecnoquips on July 19, 2008 at 1:34 pm

All of a sudden my REST routes stopped working for my ActiveScaffold controllers. No errors, not even a pointer! After a few ours of debugging, I figured out that the plugin was not being loaded for some odd reason. Since the last plugin to load was ActiveMerchant, I guessed correctly that this may be the culprit and deleted the it entirely. Voila! ActiveScaffold was working again!

The problem? Well, I accidently installed the ActiveMerchant Rails 2.1 version instead of an older one! This may have caused the loader to ignore plugins that follow it in the load sequence!

Once again, a lot of energy gone waste! I wish I had read a bit more before installing ActiveMerchant! I now use the gem version instead.

Amazon S3, jwflvplayer, Rails & Error 2048

In Uncategorized on July 15, 2008 at 11:57 am

Never thought that it would be so hard to get my Rails app to play an MP3 file uploaded to Amazon S3 on the jwflvplayer.

I initially had the player refer to the file directly, i.e, I stuck in the S3 url directly to the file flashvar. This did not work. After reading some of the FAQs, I realized that the problem was due to the fact that the flash player has some tough time with the some of the characters in the URL. One of the suggested solutions was to urlencode the offending parameters. A better suggestion was to redirect the URL and that is exactly what I did!  Here is quick snippet of what I did…

In the view, the embedded player code looks like the one below.

<div style=”float:left; padding:5px 5px 5px 0;”>
<embed
src=”http://www.jeroenwijering.com/embed/player.swf”
width=”300″
height=”200″
allowscriptaccess=”always”
allowfullscreen=”true”
flashvars=”file=http://localhost:3000<%= video_blog_path(blog) %>&config=/flash/config.xml&id=hcplayer”
/>
</div>

Note the ‘file’ value now contains a pretty url! Now in my controller, I had the following code

def show
blog = VideoBlog.find_by_id(params[:id])
redirect_to blog.video_access_url
end

The ‘video_access_url’ is a method on my model which returns an authenticated S3 URL. We will come to this later.

After setting this up, I now started getting an Error 2048 on the player. Digging around on the internet, I realized that the problem now had to do with the security settings for the flash player. Here are some links that provide an explanation of the error.

http://livedocs.adobe.com/flex/201/langref/runtimeErrors.html

http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_14213

The solution was to create a ‘crossdomain.xml’ file and insert that into the root of the server serving the flash/mp3 file. My crossdomain.xml file contains the following:
<?xml version=”1.0″?>
<!DOCTYPE cross-domain-policy SYSTEM “http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd”>
<cross-domain-policy>
<allow-access-from domain=”*”/>
</cross-domain-policy>

While this sounds like an easy thing to do, there are some additional things that needed sorting out. My authenticated S3 urls are of the form http://s3.amazon.com/<bucket>/… According to the instructions, I had to place the crossdomain.xml file at the server root. That would mean getting access to http://s3.amazon.com !!!!

Digging around further, I found out that given a bucket list, you can create a virtual root that points to ‘http://s3.amazon.com/<bucket>’. However, this involves some amount of work. Fortunately, one can also access this root by prepending the bucket name to the URL!! Wow! Therefore, my bucket root can now be accessed through ‘http://bucket.s3.amazon.com’. I can now place the ‘crossdomain.xml’ file into my bucket root and get rid of the annoying error!I am all set!

Hmm..not yet!

I use the AWS S3 library in conjunction with attachment_fu to upload my files. Attachment_fu has a method ‘authenticated_s3_url’ which returns a url for private content that applications can use. Unfortunately, this URL is of the format ‘http://s3.amazon.com/<bucket> …! I now had to tweak the plugin to get the URL in the format that I need!  Below is my modified ‘authenticated_s3_url’ method.

def authenticated_s3_url(*args)
thumbnail = args.first.is_a?(String) ? args.first : nil
options = args.last.is_a?(Hash) ? args.last : {}
url = S3Object.url_for(full_filename(thumbnail), bucket_name, options)

# Tweak the URL so that we now have the bucketname in the begining of the URL
# This is required to ensure that we can store files like crossdomain.xml at the
# root of the folder!
url.sub!(“#{s3_hostname}/#{bucket_name}”, “#{bucket_name}.#{s3_hostname}”)
end

Having got this far, I was pretty convinced that everything should work smoothly! I refreshed my webpage and was able to see the system access the mp3 data and that the 2048 error had disappeared. However, the mp3 was still not playing! I tried a lot of stuff here and there and still the file would not play! Frustrated, I was back to Googling! By luck, I came across another post that hinted at this issue. The S3 URL returned by the ‘authenticated_s3_url’ method, appends some strings at the end of the filename. Due to this, the flash player was unable to figure out the media type! The solution: add ‘type’ to the flashvar! My flashvar now looks like the one below

<div style=”float:left; padding:5px 5px 5px 0;”>
<embed
src=”http://www.jeroenwijering.com/embed/player.swf”
width=”300″
height=”200″
allowscriptaccess=”always”
allowfullscreen=”true”
flashvars=”file=http://localhost:3000<%= video_blog_path(blog) %>&config=/flash/config.xml&id=hcplayer&type=mp3
/>
</div>

Refresh page and bingo! The flash player can now play my media files from S3!!

Follow

Get every new post delivered to your Inbox.