Tuesday, July 28, 2009

Avoid ActiveRecord::RecordNotFound Errors

When querying a database for specific model IDs, Active Record normally returns an "ActiveRecord::RecordNotFound" error if the model ID you are searching for does not exist. For instance, if you run the following command:


Post.find(1)


and record #1 does not exist, you will get the Active Record error. In some cases, however, it's actually desirable for Active Record to return nil for the result instead of producing this error. In these cases, use the 'find_by_id' method instead of the 'find' method. For instance, you could run this command instead:


Post.find_by_id(1)


and you will simply get back an empty set. This method can also be used inside of the 'will_paginate' helpers like so:


Post.paginate_by_id(1)


and again you will end up with an empty page with zero results instead of the normal Active Record error.

Thursday, March 19, 2009

Manually Accessing Sessions in Rails 2.3

Due to some limitations with the Google Earth browser plugin, I'm forced to manually access my Rails session to retrieve data that is used in a dynamic KML file. Previously, in Rails 2.2, I did something like this to access my ActiveRecord-based session:


CGI::Session::ActiveRecordStore::Session.find_by_session_id(id)


In Rails 2.3, this doesn't work any more and you are presented an error of the form:


uninitialized constant CGI::Session


To fix this, I found this post, which notes to use


ActionController::Session.find_by_session_id(id)


instead. However, per the Rails API docs, that only works for CookieStore, AbstractStore, and MemCacheStore. If you are using ActiveRecord for your stores like I am, this syntax instead is:


ActiveRecord::SessionStore::Session.find_by_session_id(id)

Thursday, February 19, 2009

Include the Table Name In the Rails options_for_select Form Helper

In a Rails application, I have an advanced search form that allows the user to select any column from the database to search on. This is currently set up to use an HTML select element with all of the column names listed as option elements.

To make my searching easier, I wanted to show just the name of the column in the option element but have it return the name of the parent table and the column name. For instance, I wanted the HTML to look like the following:


<select>
<option value="my_table.column_name">Column name</option>
</select>


The Rails API documentation shows many examples of using collection of objects from a model etc., but I couldn't find any examples using the column names from the model. So, after many failed attempts, I finally managed to get this syntax to work:


<%= options_for_select(MyTable.column_names.collect {|col| [col, "my_table." + col]} %>


In this example, I grab the column names using the built-in Rails method, then pass that array of strings to Ruby's collect method. The collect method accepts a block that allows me to create a new array where each element is itself an array. In these smaller arrays, I insert the column name directly and a string with the table name added to the beginning. The array created by the collect method is now of the proper format expected by the Rails options_for_select form helper.

I didn't think it would be this difficult, but in the end, I think the single line of code is pretty clean and simple.

Update
Well, I guess my idea wasn't that new and cool. As soon, as I posted this, I found the same solution in the API docs after all. I was just looking in the options_for_select section, not the select selection. See:

http://api.rubyonrails.com/classes/ActionView/Helpers/FormOptionsHelper.html#M001592

Wednesday, February 11, 2009

Ruby: Require All Files In A Directory

In my Rails app, I have an external program that I keep in my lib directory for offline processing. Within that program are several ruby classes that I'd like to load at startup. Rather than adding require statements for each one and running the risk of forgetting one, you can load the whole directory with the following line of code:


Dir.glob(File.join(File.dirname(__FILE__), 'images/*.rb')).each {|f| require f }


where, in my case, I'm loading all of the *.rb files in my lib/images folder. Now, I can add new files to that directory and they will automatically get loaded at during startup of my external program.

See this link for more information.

Friday, January 30, 2009

Redirects for restful_authentication

My Rails app is not deployed at the root level of my server (e.g. http://myserver.com). In order to be able to serve up multiple mongrel_clusters for multiple Rails apps, users must access the site at http://myserver.com/myapp/.

This caused one unforeseen issue with the restful_authentication plugin. After installing this plugin (or gem), a file named authenticated_system.rb is added to your app's lib directory. Inside that file is a method called 'redirect_back_or_default' that is used to redirect the user every time they perform a login or logout. This method in turn is then called by your Sessions controller (again, added by restful_authentication).

When I attempted to login or logout from my app, I was constantly redirected to the root level of our server instead of the root level of my app. This is obviously not what I wanted, and instead would prefer that users get redirected to the root URL for my app.

The 'redirect_back_or_default' method takes a default value as an input. So, to fix this, you simply need to modify your sessions_controller.rb file to include the proper default for your application. In my case, I replaced the '/' value that was included in the Sessions controller by default with the 'root_url' helper. Now when users logout, they return to the homepage of my application.

Tuesday, January 13, 2009

Rails 2.2.2 + mySQL + Windows

Doing Rails development on Windows just plain sucks. Here's another reason why. Upon upgrading to Rails 2.2.2, I started getting mySQL errors. For one, the Ruby-based mySQL gem is no longer included with Rails 2.2.2. Secondly, the Windows mySQL gem is broken and doesn't install its help docs. Here's what helped me get back up and running:

1. Install the Windows mysql gem (gem install mysql) with the --no-rdoc and --no-ri options.

2. Copy libmysql.dll from your mysql/bin installation to your ruby/bin installation. No clue why. Just do it.

[Reference]

Allow MediaWiki To Use ImageMagick 5.x

I was hoping to use ImageMagick with MediaWiki for image uploads and resizing. Unfortunately, I only had ImageMagick version 5.x installed. With this version, MediaWiki produces and error since it is trying to send the -thumbnail option to ImageMagick's convert function.

In version 5.x of ImageMagick, -resize does basically the same thing (-thumbnail just strips the metadata from the image). So, instead of upgrading to version 6.x of ImageMagick, a quicker solution was to add the following to my LocalSettings.php file:

$wgCustomConvertCommand = "/usr/sfw/bin/convert -resize %wx%h %s %d"

This line is documented in DefaultSettings.php and is meant for using another graphics library like GM. But instead, I just added in the convert command for ImageMagick 5.x. Note that this line would be added to LocalSettings.php in place of the $wgUseImageMagick and $wgImageMagickConvertCommand variables.