Annoying Flash Issues
Posted by Sam
So I'm working on the Barkley Holiday site for 2007 and I ran into several frustrating things today. A little background on the site. The backend is written in Ruby on Rails and the frontend is flash based. I use LiteSpeed's excellent web server for the application and web server. The backend of the site is pretty simple. It's using the attachment_fu plugin to upload and resize photos and then simple XML to communicate with the Flash frontend.
The first problem I had today was that Flash couldn't get the XML when running inside IE6 on Windows. It works everywhere else. Grrr. The Flash developer found an article that was mostly wrong, but had just enough truth to help me find the real problem. When using rxml templates Rails will automatically return a content type of 'application/xml'. For whatever reason when you combine this with gzip compression, Flash and IE6 you can run into a situation where IE6 won't push the XML to Flash. If you turn off the compression it works fine. I turned off compression in LiteSpeed for dynamic content and everything worked. I really wanted the compression so I kept poking around to see if I could find another solution. Turns out if you leave compression enabled and change the content type to 'text/xml' then everything works fine. Stupid Internet Explorer! So if you are using Flash with RXML, IE6 and dynamic gzip compression you should set the content type like so.
@headers['Content-Type'] = "text/xml"
The next problem I had with Flash was that images weren't being resized with attachment_fu when they were uploaded from the Flash frontend. If I loaded them with the backend HTML interface everything worked as expected. This turned out to be a relatively easy problem, but it still bugs me. Flash doesn't set the correct MIME type when it uploads files. Instead of uploading the files with a MIME type of 'image/jpeg', 'image/jpg' or something sane Flash pushes files up with a generic 'application/octet-stream' MIME type. Attachment_fu was seeing this MIME type and didn't think it was an image so it wouldn't resize it. Since we are only uploading images to this particular application I hacked the attachment_fu plugin to accept 'application/octet-stream' as a valid image MIME type. There might be a better way to do this but I needed it done yesterday so here is the original code found in attachment_fu > lib > technoweenie > attachment_fu.rb.
#original code
And here is the code with the MIME type needed to process Flash uploads.
@@content_types = ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg']
#hacked code
@@content_types = ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg', 'application/octet-stream']
I'm not sure if the first problem that I ran into is Flash's fault or IE6, but the second issue definitely seems like a problem with Flash. The browsers push up the MIME type so why can't/doesn't Flash?
Tags: rubyonrails litespeed
The little things
Posted by Sam
It's the little things in life that make a big difference. I recently ran into a problem where I thought ImageMagick was corrupting my images when it resized them. Turns out the problem was the database. In my migration I'd only specified :binary for the datatype. It looked like this.
create_table :db_files do |t|
Well in MySQL this means that it defaults to a Blob which only holds 64k. Originally the images were being scaled to 182x182 so this didn't present a problem as all the images seemed to come in under 64k. A couple days later I had to adjust this to 250x250 and then we started getting 'corrupt' images. Turns out some images just needed more space and some didn't. I looked through my Agile Web Development in Rails book and only saw a Binary datatype and didn't find an obvious way to make it bigger. Then I stumbled across a page that talked about setting the size to have a bigger limit and ActiveRecord will automatically give you a larger Blob datatype. In order to accommodate the bigger images I created the following migration.
t.column :data, :binary
end
class ChangeMaxImageSize < ActiveRecord::Migration
Woo Hoo! Thankfully that solved it.
def self.up
change_column :db_files, :data, :binary, :limit => 512.kilobytes
end
def self.down
change_column :db_files, :data, :binary
end
end
Some frameworks look great on the surface and the more you use them the uglier they get. That was certainly my experience with Struts. It created as many problems as it solved. I've had a very different experience with Rails. It constantly surprises me with how well thought out and usable it is. I'm not a Rails fanboy I just like things that work and for most cases Rails just works.
Tags: rubyonrails
NexentaStor ZFS Based Storage Appliance
Posted by Sam
Anybody that knows me knows that I think ZFS is the best thing since sliced bread. As far as file systems go it's pretty much the best thing to come along in years, maybe decades. I've tried to evangelize it to my Windows brothers but asking them to switch to Solaris for a file system seems to be too much to ask for and it seems unlikely that Microsoft would ever be as progressive as Apple and include it in the operating system. Instead they will no doubt try to clone it, spending millions of dollars in the progress and still ending up trailing ZFS. Ok, enough ranting about the boring giant that is Microsoft. They haven't done anything interesting in years.
NexentaStor takes OpenSolaris and ZFS and packages it up into a neat little NAS appliance complete with a web based GUI for controlling NFS, CIFS (SAMBA), iSCSI, FTP and ZFS snapshots. You provide the hardware and the drives and Nexenta provides the software for running the NAS.
Nexenta provides a free VMware image that you can use to install and test NexentaStor. It appears to be a full featured copy. If you want to run NexentaStor on a physical server you have to purchase it from Nexenta. They don't provide any pricing on their site currently, but I'm sure it will be very cost effective. I've seen pretty poor network performance with Solaris on VMware ESX servers so I don't recommend running NexentaStor on VMware if you require the best performance, but it's great for trying out the product before you buy.
Installing and running NexentaStor was extremely easy under VMware Fusion on my MacBook. I had it running within 30 minutes with no real problems. I've got CIFS and FTP up and running but I haven't been able to get NFS running so far. Also, I'd like to play with joining it to an AD domain. This feature would be great for Windows admins looking for the rock solid reliability of Solaris and ZFS without requiring Windows admins to learn Solaris and everything that goes along with that. For a product that isn't even a 1.0 product it looks pretty amazing so far. I look forward to playing with NexentaStor some more in the future.
Tags: zfs
Ruby DTrace Probes in Leopard
Posted by Sam
There are a ton of new features in the upcoming release of Mac OS X code named Leopard, but there are a couple of features that I find pretty exciting and interesting but haven't seen mentioned elsewhere. The first is that Apple added DTrace probes to their version of Ruby. See the official page here. These probes were available on Solaris for a while thanks to Joyent, but I didn't realize Apple was including them in Leopard.
The second interesting feature (interesting to developers at least) is an app called Instruments. You can use DTrace probes to see exactly what is happening inside your Rails app while also seeing exactly what affect it's having on your system. It's got a great gui that I think will extremely useful for tracking down performance problems.
Mac OS X was already the platform of choice for Ruby on Rails developers but now it's even better. Apple is doing a great job of picking the best technology available and tying it into their OS. Now the only thing I'm waiting for is full ZFS support! For me it's Solaris on the servers and OS X on the clients. This combination will take over the world. Mark my words.
Tags: macosx dtrace rubyonrails
Easy Custom Environment in LiteSpeed for Rails
Posted by Sam
Update (8/12/2008)
Thanks to LiteSpeed adding a staging environment this work around is no longer necessary for me, but I'm leaving it here in case others need custom environments besides staging.
Ruby on Rails has three standard environments. Development, test and production. Test mode is also called staging by a lot of people, including myself. Unfortunately, my favorite web server and all around best Ruby on Rails application server, LiteSpeed, doesn't have a test mode. For whatever reason they implemented the development and production modes for Rails but didn't include a test mode. This is annoying because any real application development should be going through some formal or informal QA and this should be happening on a dedicated staging environment.
There are a couple of ways around LiteSpeed's lack of a test mode for Ruby on Rails. One of them is to simply set the RAILS_ENV variable in the environment.rb file like so.
# Uncomment below to force Rails into production mode when
I don't like this because if you push this exact same code to production it will override the default value, which should be production. That could cause all kinds of problems. Since I do all my pushes (both personal and professional) straight from subversion I would have to remember to make this change every time I pushed a site update to staging. It just feels wrong.
# you don't control web/app server and can't set it the proper way
ENV['RAILS_ENV'] = 'test'
Another options is to forgo the easy Ruby on Rails setup in LiteSpeed and do a custom setup as described here. But then you will have the problem this guy had. Obviously it's doable but still seems dirty.
I prefer to stick with the standard and obvious way of doing things whenever possible. When you have to quickly migrate a server at 3 in the morning I have learned that keeping things straight forward is the best approach. Sometimes I will go to great lengths to keep something simple when a quick and dirty approach would have sufficed for a while. Keeping things standard and clean is the best approach. So, that being said, this is the approach that I think works best for setting up a test (or staging as we call it) environment in LiteSpeed. Change the environment.rb file in your Rails so that it reads:
# Uncomment below to force Rails into production mode when
Basically you are saying if you don't know what your environment should be, set it to test. Now you need to make sure that the RAILS_ENV is not set by LiteSpeed so go to Configuration > Virtual Host Templates > EasyRailsWithSuEXEC > Context > Edit and select the blank option in the Rails Environment section. Restart LiteSpeed and your custom environment should be loaded.
# you don't control web/app server and can't set it the proper way
ENV['RAILS_ENV'] = 'test' unless ENV['RAILS_ENV']
Tags: rubyonrails litespeed