Monthly Archives: December 2007

Textmate not recognizing html.erb in Rails HTML Bundle

With Ruby on Rails 2.0.2 fresh out of the gates and hordes of (us) DHH fanboys coding away in Textmate on their Macs will soon realize that the new .rhtml template is now .html.erb. This file extension isn’t recognized as Rails (HTML) by default in Textmate 1.5.7.

All you need to do is edit the correct Textmate Bundle which you get to by finding in the Textmate Menu: Bundles -> Bundle Editor -> Show Bundle Editor -> click the arrow beside Ruby on Rails -> near the bottom of the list click on Rails (HTML), then on the right hand side area find:

fileTypes = ( 'rhtml' );

and change it to:

fileTypes = ( 'rhtml', 'erb' );

Greg is the man and posted the original fix to the Textmate html.erb bundle problem.

Import Google Bookmarks into Camino Browser

If Camino 1.x isn’t importing your Google Bookmarks (http://www.google.com/bookmarks) properly (it can hang during the import process) an easy fix or solution is to import your Google bookmarks into Safari first (File menu > Import Bookmarks).

Then from Safari, export the bookmarks to an HTML file.

Then return to Camino and import the bookmarks from an HTML file (File menu > Import Bookmarks > Select a File [from the drop down box] and select the Safari bookmarks.html file that you just created).

MySQL ruby gem install problem on Mac OS X Leopard

For those of you using MySQL database server on Mac OS X Leopard while developing for Ruby or Ruby on Rails, you might have run into an issue with the mysql rubygem installing OK, but not actually loading properly in irb, nor completing unit tests successfully.

If you’ve seen errors such as:

$ irb
>> require 'mysql'
LoadError: dlopen(/Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle, 9): Library not loaded: /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib
Referenced from: /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
Reason: image not found - /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
from /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:32:in `require'
from (irb):1

Or perhaps you’ve tried to run test.rb from the mysql ruby library install and ran into an error like this:

$ ruby test.rb
./mysql.bundle: dlopen(./mysql.bundle, 9): Library not loaded: /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib (LoadError)
Referenced from: /Library/Ruby/Gems/1.8/gems/mysql-2.7/mysql.bundle
Reason: image not found - ./mysql.bundle from test.rb:5

The fix to the mysql ruby library gem installation was provided by jhclouse on the RailsForum site. I’ve edited the fix to work with Mac OS X Leopard’s pre-installed version of Ruby:

sudo install_name_tool -change /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib /usr/local/mysql/lib/libmysqlclient.15.dylib /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle

The only difference between jhclouse’s fix and the one here is the location of the installed mysql rubygem. On OS X Leopard, ruby gems are installed in the /Library directory rather than /usr/local/lib.

Run the fix again in the main mysql ruby gem directory as there is another mysql.bundle file that needs fixing. This bundle file is used by the unit test file test.rb.

sudo install_name_tool -change /usr/local/mysql/lib/mysql/libmysqlclient.15.dylib /usr/local/mysql/lib/libmysqlclient.15.dylib /Library/Ruby/Gems/1.8/gems/mysql-2.7/mysql.bundle

To run the unit tests for the mysql ruby gem you need to supply some command line arguments to test.rb:

ruby test.rb -- localhost [username] [password]

Replace [username] [password] with valid credentials for your MySQL server and you should have a fairly successful run of the unit tests for the mysql ruby gem.

Now that you’ve got the mysql C bindings for ruby installed, lets double check that it’s actually being used.

If you have a rails project, start with webrick (script/server) and load up your test site in a browser. Do something within your site that you know touches the database.

Now find the process_id for ruby by running ‘top’ in the command line. Top will return a list of all process names and their process ids. Find ruby amongst the list. For me it happened to be 3343.

Then we use that process_id in a magical program called ‘lsof’:

$ top
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
3372 top 5.3% 0:01.39 1 18 29 824K 188K 1416K 18M
3343 ruby 0.3% 0:06.77 2 19 247 60M 188K 64M 85M

$ lsof -p 3343 | grep mysql

ruby 3343 ben txt REG 14,2 86288 813474 /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
ruby 3343 ben txt REG 14,2 1967788 624481 /usr/local/mysql-5.0.45-osx10.4-i686/lib/libmysqlclient.15.dylib

lsof spits out the “list of open files” that are in use by a certain process, in this case the running ruby process that is serving our Rails site. In the above listing lsof shows that the freshly installed mysql ruby gem (mysql-2.7) that provides native C bindings for ruby to use when accessing MySQL, is currently being used. Sweet, we’re all good.

So is all this trouble really worth it? Why not just use the built in ruby libraries to interface with MySQL? If your Rails site touches a database, and most likely it does, you’ll see a 2-5x decrease in rendering time due to database calls. We’re only talking milliseconds, but it’s still a 2-5x boost in efficiency so it’s definitely worth it if you’re optimizing your Rails site. Whether it should be at the top of your tweaking to-do list depends on how optimized everything else is.

My Rails site in the testing environment was constantly generating on average about 30% of its page rendering time due to database activity. The following is hardly a definitive test, but is printed here simply for interests sake.

For an initial site load with the MySQL query cache reset, my home page rendering time looked like this before the C MySQL ruby binding installation:

Completed in 1.47017 (0 reqs/sec) | Rendering: 0.10060 (6%) | DB: 1.18992 (80%) | 200 OK [http://localhost.com/]

After, resetting the query cache in MySQL, clearing the browser cache and restarting webrick, the initial site home page load after installing the C bindings for MySQL via the ruby gem:

Completed in 0.70598 (1 reqs/sec) | Rendering: 0.08854 (12%) | DB: 0.56506 (80%) | 200 OK [http://localhost.com/]

The time to load was cut in half and the only thing that changed was the way ActiveRecord accesses the MySQL database.

Please note that if you’ve been using Mac Ports, this fix may need tweaking on your part. The problem and the fix are pretty straight forward once you know about the install_name_tool program. The mysql ruby gem is simply looking in the wrong place for a MySQL library that it needs to interface with. If you look closely at the first two directory paths you’ll notice that the first has an extra “/mysql” in between “/lib” and “/libmysqlclient.15.dylib”. Remove that extra “/mysql” folder from the directory path and you’re golden.

mod_deflate gzip compression http/1.1 vs. 1.0

If that title makes no sense to you, well… that’s good, cause you probably didn’t spend the last three hours trying to figure out why gzip compression is not working on Javascript files being served from your Apache 2.x web server.

For those of you unlucky enough to understand what I’m talking about (and thus stuck scratching your head at why Apache 2.x with mod_deflate is not compressing javascript, css, etc. files… the reason is (drum roll please): gzip compression is handled transparently by all modern browsers. Furthermore, HTTP/1.1 enabled browsers will check their cache to see if a copy of the file requested is in the cache and will not download the same file from server if present locally. Apache still receives a request for a file that is in cache, but only to check that the file version is the same, and if it is the same, Apache will not serve the file. This is the key to understanding why Apache logs report no compression on files served to a HTTP 1.1 compliant browsers… it’s cause the file was not actually sent to the requesting browser.


"GET /javascripts/prototip.js HTTP/1.1" -/- (-%)
"GET /javascripts/prototip.js HTTP/1.1" 2649/9002 (29%)
"GET /favicon.ico HTTP/1.1" -/- (-%)
"GET /javascripts/prototip.js HTTP/1.1" 2649/9002 (29%)
"GET /favicon.ico HTTP/1.1" -/- (-%)

In the above snippet of a mod_deflate log, the first line is Apache “serving” the prototip.js file, with 0Bytes [compressed] / 0 Bytes [uncompressed] (0% compression rate). The reason? The file is cached at the browser and thus the file is not actually sent.
The second line is after clearing the browser cache. It shows that prototip.js was sent to the browser as a 2649 Byte compressed file from an original uncompressed 9000 Byte file, which gives a compression rate of 29%. The favicon.ico file (for the little icons your see beside your site name in browser window tabs) is sent uncompressed due to it not being one of the file types we specified in http-vhosts.conf, therefore, no compression was applied to the file.

There is a good chance that I’m talking straight outta my butt on this. If you know better than I on this subject, please do leave a comment and let me know what’s really going on.

For reference, here is the pertinent part of my http-vhosts.conf file, with comments/junk removed.

78 AddOutputFilterByType DEFLATE text/html text/plain text/css
80 AddOutputFilterByType DEFLATE text/javascript application/x-javascript
82 BrowserMatch ^Mozilla/4 gzip-only-text/html
83 BrowserMatch ^Mozilla/4.0[678] no-gzip
84 BrowserMatch bMSIE !no-gzip !gzip-only-text/html
85 DeflateFilterNote Input input_info
86 DeflateFilterNote Output output_info
87 DeflateFilterNote Ratio ratio_info
88 LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate
89 CustomLog /var/www/test.net/shared/log/myapp_deflate_log deflate

I know you’re itchin’ for some good old HTTP Compression RFC (Request For Comments) 2616 reading so here it is.

How to play / watch .iso dvd movie files in Mac OS X Leopard

Apple DVD Player Play ISO filmsTo play a movie that is saved in ISO file format on Mac OS X, start the built-in DVD Player (find it in the Applications Folder, it won’t be on the Dock at the bottom of your screen by default).

Then in Finder (or on your Desktop) double click the ISO file to “mount” the ISO movie file.  Apple DVD Player will automatically recognize that a movie DVD has been loaded and will start playing the movie immediately.

That’s all there is to playing movie DVD’s saved as ISO files on your Mac with Leopard OS X.

SuperDuper backup not bootable in Mac OS X Leopard

If you’re having troubles booting off of a backup of your Leopard OS X install made by SuperDuper!, you’re not alone.  SuperDuper! full system backups are not bootable under Leopard. If you try to boot off a SuperDuper! created backup on an external USB disk or external firewire disk, the Mac OS X boot screen with the spinning/twirling little circle will continue forever.

ShirtPocket, the maker of SuperDuper! notes on their homepage that their SuperDuper! product is not fully compatible with Leopard, but they do not say what incompatibilities exist.  As far as I can tell SuperDuper! under Mac OS X Leopard does not:

  • Backup all personal settings such as backgrounds, menu bar items, dock preferences, keyboard preferences, etc.  Consider all of this information lost if you are planning to back up only with SuperDuper!.  You cannot use this backup to transfer your personal settings using Migration Assistant. Some things such as user accounts, passwords, files, etc. will transfer OK using Migration Assistant and SuperDuper! created backup, but nearly all other settings will not be transferrable.
  • Backup all Applications properly, such as LittleSnitch (outgoing network traffic firewall). Count on having to reinstall certain software when trying to restore from a SuperDuper! backup.

For now, consider Time Machine your preferred backup provider until SuperDuper! manages to fix the incompatibilities with OS X Leopard.  ShirtPocket makes great products and they have a stellar pricing model (unlimited trial, but pay for it if you use it).  Also, SuperDuper! is extremely easy to use and hopefully it has a niche that allows it to work side by side with Time Machine.

How to use command line debugger fdb to debug Flex / Flash on Mac OS X

Debugging Flash / Adobe Flex 2 / ActionScript 3 code using fdb on Mac or Windows is not exactly a straightforward affair. The following are instructions on how to get fdb running for debugging flash files and how to debug flex through the command line tools.

Preamble:

  • Verify that you have a debug capable version of Flash Player 9 (or more recent) on your Mac or Windows machine. You normally get this by default if you’ve installed the Adobe Flex SDK 2 or Adobe Flex Builder 2 / 3 (and have not installed/updated Flash Player since then). All web browsers that you had installed at the time of your Flex Builder / SDK installation should be updated with the Debugger versions of Flash Player 9. To check that your version of Flash Player is debug enabled, just open up any web page that has a flash component within it such as Google Finance and right click on the flash component within the browser window. You should see a context menu pop up with a “Debugger” menu item, which may or may not be greyed out. Adobe Flash Player Debugger
  • Verify that you have Adobe Flex SDK 2 installed or Adobe Flex Builder 2 / 3 installed (which contains the SDK as part of the Flex Builder install). If you’re on a Mac, the Adobe Flex SDK 2 is installed into /Applications/Adobe Flex Builder 2/Flex SDK 2, so open up Finder and check that you’ve got this Folder/directory available in /Applications.
  • create a symbolic link to the fdb program:

sudo ln -s /Applications/Adobe Flex Builder 2/Flex SDK 2/lib/fdb.jar /usr/local/lib/fdb.jar
sudo ln -s /Applications/Adobe Flex Builder 2/Flex SDK 2/bin/fdb /usr/local/bin/fdb

The following example debugs a flash file named salesforce-debug.swf. Note that you don’t debug your regular production compiled flash file, you debug, the “debug” version, which is automatically created for you when you compile your flash file or project. These files are normally located within the /bin directory of your Flex project.
If the following example, when you see prompts such as ‘$’ or ‘(fdb)’, do not mistake them for commands, those are my prompts and you should be typing what follows those prompts. Lines not preceded by either a bullet or prompts are output from the fdb program.

To debug a Flash .swf using fdb on a Mac:

  • launch the Terminal program (from /Applications/Utilities/Terminal)
  • change directories / folders until you’re in the same directory as the .swf file you want to debug
  • launch fdb

$ fdb

  • when you start up fdb you should see an fdb prompt: (fdb)
  • you need to specify the .swf file you want fdb to hook into and debug

(fdb) file salesforce-debug.swf
(fdb) run
Attempting to launch and connect to Player using URL
salesforce-debug.swf
Player connected; session starting.
Set breakpoints and then type ‘continue’ to resume the session.
[SWF] Users:ben:Documents:Flex Builder 2:salesforce:bin:salesforce-debug.swf – 1,101,498 bytes after decompression

  • At this point a browser window should pop-up and begin to load your flash .swf file, but it will not finish loading until you’ve set your breakpoints and tell fdb to ‘continue‘. Setup your breakpoints now by using the ‘break’ keyword followed by a function name or a line number. In the following I set a breakpoint in my function ‘sfquery’ which will stop the Flash .swf when it hits this function and you’ll get a prompt in fdb debugger.

(fdb) break sfquery
Breakpoint 1 created, but not yet resolved.
The breakpoint will be resolved when the corresponding file or function is loaded.

  • At this point the browser window with the half-loaded Flash file is still hung at “Loading…”. Repeat with as many breakpoints as you need. When done with breakpoints, you must issue a ‘continue’ command to get Flash to continue loading the .swf for debugging.

(fdb) continue
Additional ActionScript code has been loaded from a SWF or a frame.
To see all currently loaded files, type ‘info files’.
Resolved breakpoint 1 to salesforce.mxml:64

  • Ok, this step is key to the debugging setup in Flex… you have to hit Return/Enter at an empty fdb prompt in order to get the your Flash file / Flex project to actually finish loading and to run in the browser window when in debug mode. No, there are no instructions for this, you just have to figure this out on your own through trial and error. Before this the browser window should have the Flash file running but frozen and “loading” until you hit the Enter key while in the fdb debugger, which is the next step:

(fdb) [hit the Enter button here at this blank prompt]

  • Finally at this point your browser should finishing loading up the Flash file you’ve just set up for debugging and it should be ready for action. If you see a blank page that is still “loading”, go back into the Terminal and spank the Enter / Return button a few more times and see if the browser page responds by loading up your Flash debug file. Hopefully it does. And if it doesn’t, you’re back to square one. If you are reading this and have found other solutions to get fdb to actually work, please submit a comment and I’ll add it to this posting.
  • Now when you use your .swf file and hit the function that you’ve set a breakpoint for as mentioned previously, the Flash program will freeze and when you go back to fdb in the Terminal window you should see something like the following:

[trace] Method name is: login
[trace] Method name is: login
Breakpoint 1, salesforce.mxml:64
64 private function sfquery():void {
(fdb)

  • This is where you’ve hit paydirt. At this (fdb) prompt you can now start inspecting variables using ‘p’ <var_name>, step over lines using ‘n’, list lines of code with ‘l’, list previous lines of code with ‘l -‘, get help by typing ‘help’, step out of the current function with ‘finish’, and continue executing the program with ‘continue’.
  • After you’re finished debugging the function you’re in, type ‘continue’ to return focus back to your web browser that is running your Flash program and this will return you back into normal running mode.
  • To quit debugging just go into the Terminal running fdb and type ‘quit’

quit
Do you want to attempt to halt execution? (y or n)

  • Enter ‘y’

Attempting to halt.
To help out, try nudging the Player (e.g. press a button)
Execution halted 00041994at 0xExecution halted 00041994 (268692)

  • Just enter ‘quit’ again

The program is running. Exit anyway? (y or n)

  • Enter ‘y’ again and you should be returned back to your Terminal prompt

That’s about it for getting the Flash Debugger to work in Mac OS X.

Here’s a useful page of fdb debugger commands to use while debugging Flex or debugging Flash .swf files.

Common errors when trying to debug Flash and Flex:

  • A common error message with an incorrectly setup fdb flash debug session is the following: “A connection to the Debugger or Flash Player could not be established by Adobe Flash Player 9”. This happens when you simply start the debug version of a flash file, load up fdb, issue a ‘run’ command in fdb, then right click the Flash file and choose “Debugger” from the context menu. Although this would make a lot of sense in how to setup the command line debugger… it simply does not work this way.
  • Another common error to see within fdb command line debugger itself is: “WARNING: The Player that you are using does not support all fdb commands.”. This is not the reason why you cannot debug in fdb. This warning message is only issued when you’ve setup an fdb debugging session incorrectly, like in the previous example.
  • “Where is the debugger or host application running? Localhost or Other Machine” This is another question you should never see if you’ve setup your Flex debugging session correctly. Following the above step by step instructions for debugging a Flash / Flex project or file should avoid this error.Flash Debugger Pop-up question

Good luck and let me know if you have any tips to add to this.