A collection of computer systems and programming tips that you may find useful.
 
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Wednesday, June 30, 2010

Rails Routes and Models with 'Uncountable' Names

Rails follows the convention of using singular and plural forms of model names for various purposes. For example user.rb for a Model name and users_controller.rb for the controller.

Every once in a while you need a model where the singular and plural forms are the same. I just ran into that with a model called 'species'. This can cause you all sorts of hurt but here is a way round it.

First of all, decide if you really need to use that name. If you can figure out an equivalent where singular and plural forms are different then use it - much simpler... but if like me there is no good alternative then you do this:

1: Tell the built-in pluralization functions to skip your name.

In config/initializers/inflections.rb add this:
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w( species )
end
2: Create your model, controller, table etc in the normal way using 'species' as the model name.

3: In your routes.rb give the :species resource an artificial singular form:
ActionController::Routing::Routes.draw do |map|
map.resources :species, :singular => :species_instance

Doing this allows the routing magic to distinguish between singular and plural. But the downside is that you need to change a bunch of controller and view paths.

4: run 'rake routes' to see what Rails expects your new routes to look like.

5: In your controller, change any 'redirect_to @species' lines to 'redirect_to species_instance_path(@species)' (Should be just create and update actions).

6: In your index.html.erb view change:
link_to "Show", species
to
link_to "Show", species_instance_path(species)
In doing so you make it explicit that you want the singular form.
Similarly, change the following:
"Edit", edit_species_path(species)
becomes
"Edit", edit_species_instance_path(species)

link_to "Destroy", species ...
becomes
link_to "Destroy", species_instance_path(species) ...

and finally
link_to "New Species", new_species_path
becomes
link_to "New Species", new_species_instance_path

7: In your show, new and edit view pages, make similar changes. Links back to the index page can stay as 'species_path' but edit, delete and new links should be updated as shown above.

It's messy, for sure, but it solves the problem and allows you to retain 'natural' names in the user interface and in the URLs that users will see.



 

Tuesday, May 11, 2010

Compiling Ghostscript on Intel 64 bit Mac OS X

Ran into problems getting Ghostscript to compile on an Intel Mac running Snow Leopard.

The error messages were telling me it was trying to compile a 32 executable, and then after fixing that it complained that libraries in /opt/local/lib were compiled for 32 bit. The thing is, except for some old mac ports stuff, I don't use /opt/local!

I was able to fix compile successfully with three steps.

1: Take the old /opt/local/lib code out of the picture by renaming the directory to a temporary name. I can bring it back if it turns out something actually relies on it.

2: Rub ./configure with CFLAGS and LDFLAGS defined. These end up getting passed to 'make'
$ ./configure CFLAGS='-arch x86_64' LDFLAGS='-arch x86_64'


3: Compile it 'make' (with no flags) and install with 'sudo make install'

Not sure yet if it can pick up all the fonts that it needs - we'll soon see...


 

Image Resizing with Rails Paperclip and ImageMagick

The Rails Paperclip plugin uses ImageMagick for creating thumbnail images, etc.

You specify the size of images using ImageMagick's Geometry syntax which can be a little confusing. Here are the aspects of that which are most useful for Paperclip users.

The basic specification is <width>x<height> in pixels, optionally followed by a modifier. In some cases you can omit either width or height.

  • 256x256

  • This specifies the Maximum dimensions for the image, while preserving the aspect ratio of the image. So if your image were actually 512x256 it would be resized to 256x128 in order to fit inside the specified size.

  • 256x256!

  • This specifies the Exact image size, so a 512x256 image would be changed into 256x256, losing the aspect ratio.

  • 256x

  • This specifies the desired width of the target image, leaving the height to be set so as to preserve the aspect ratio.

  • x256

  • This specifies the desired height of the target image, while preserving the aspect ratio.

  • 256x256^

  • This specifies the Minimum size for the target image, so the resized image may be larger than these dimensions.

  • 256x256>

  • This specifies that the image will be resized only if it is Larger than the dimensions.

  • 256x256<

  • This specifies that the image will be resized only if it is Smaller than the dimensions.


Other options exist within the syntax. See the ImageMagick docs for more details.


 

Monday, May 10, 2010

Rails, Paperclip and ImageMagick

Ran into trouble generating Thumbnail images using the Paperclip plugin, which delegates the image manipulation to ImageMagick.

The error was "Paperclip::NotIdentifiedByImageMagickError: /tmp/stream,33194,0.jpg is not recognized by the 'identify' command".

A LOT of people have run into this - here is my solution.

In my setup I'm on MacOSX with a binary download of ImageMagick in /usr/local/ImageMagick-6.6.1/bin and I'm running Rails under Apache/Passenger. I've got Paperclip installed as a plugin.

There are 3 steps needed to get this working:

1: Make sure you have ImageMagick working at the UNIX command line level. This involves adding it to your path and exporting these environment variables (pointing to your ImageMagick installation, of course)
MAGICK_HOME=/usr/local/ImageMagick-6.6.1
DYLD_LIBRARY_PATH=/usr/local/ImageMagick-6.6.1/lib
Check that identify works with your images at the command line level. If not then fix those problems first.

2: Tell Paperclip where to find the ImageMagick executables
In config/environment.rb add this at the bottom of the file
Paperclip.options[:command_path] = "/usr/local/ImageMagick-6.6.1/bin"
At this point, after restarting Passenger, you would see that 'identify' is run from within Paperclip but is not able to identify the file... the final step is...

3: Identify needs those two exported environment variables - and Apache/Passenger (or other web servers probably) does not pass those through by default!
In your passenger vhost file add these lines:
SetEnv MAGICK_HOME /usr/local/ImageMagick-6.6.1
SetEnv DYLD_LIBRARY_PATH /usr/local/ImageMagick-6.6.1/lib
Restart apache/passenger and it should work fine.

For me, the binary installation of ImageMagick has worked fine so far. Compiling it yourself is a real pain (make sure you compile for x86-64 if you are on an Intel Mac) - but you don't need to do it. Likewise, you do not need the Rmagick gem if you are using Paperclip, at least for basic image resizing, etc.


 

Tuesday, April 20, 2010

Suppressing newlines in Ruby ERB documents outside of Rails

In ERB files the standard <% ... %> tag pair will result in a newline being added to the output.

In Rails you can add a minus sign before the closing tag to suppress this:

<% ... -%>

But if you use ERB outside of Rails, this will produce an ERB compile error.

The way to handle this is to leave out the minus signs and instead specify the trim_mode when you create a new ERB object. There are 3 options for this parameter:
    %  enables Ruby code processing for lines beginning with %
<> omit newline for lines starting with <% and ending in %>
> omit newline for lines ending in %>

Setting the trim_mode requires that you also set a safe_level, but this is normally set to 0. So to suppress newlines on all lines with ERB tag pairs create the ERB object like this:
erb = ERB.new(template_file, 0, '>')

This solves the newline issue for me but it would be nicer to have the per-line option available in Rails.

You can also set the global trim_mode in Rails if you want to. in environment.rb:
config.action_view.erb_trim_mode = ">"




 

Wednesday, March 31, 2010

Script aliases in the style of git

The Git version control software lets you run its commands either through as a single program name followed by the command as an argument (such as git status), or as individual scripts (such as git-status).

The advantage of the second form is that you can use the text completion feature of your shell to save you some typing. It's a personal preference...

It is implemented by a series of symlinks from the longer command names to a single git executable. git itself gets the name of the executable it was called as and breaks that down to get the name of the command.

It is easy to create your own version of this. Here it is in Ruby...

The 'primary' script is called myscript.
#!/usr/bin/env ruby
script = File.basename($0)
if script =~ /^\S+?_(.*)$/
command = $1
else
command = ARGV.shift
end
puts "command #{command}"

if ARGV.length > 0
puts "args #{ARGV.join(', ')}"
end

Create an alias to it by adding a suffix (the sub command name), separated by some delimiter and symlinking this to the primary script:
$ ln -s myscript myscript_cmd_0
$ ln -s myscript myscript_cmd_1

The script looks at how it was called ($0 in Ruby) and sees if it can split off a command. If it does then it takes any other arguments as they are presented. If you call the script as the primary script followed by a separate command then it shifts ARGV to get the command. These examples show how it works.
$ ./myscript_cmd_0 foo bar
command cmd_0
args foo, bar
$ ./myscript_cmd_1 foo bar
command cmd_1
args foo, bar
$ ./myscript cmd_1 foo bar
command cmd_1
args foo, bar


You don't want to use a technique like this all the time - you end up with loads of symlinks in your bin directory, but in the right situation it can be very useful.


 

Thursday, March 18, 2010

Merging PDF Documents in Preview on Mac OS X Snow Leopard

Preview in Mac OS X is not only a viewer for PDF (and other) documents, it allows you to merge multiple PDF documents into one. This is useful for a lot of reasons, especially when you have scanned several pages of a documents into individual files and you want to combine them.

In Snow Leopard the way this works has changed and, as there is no menu item for merging, it can be a little confusing.

Open your first 'page' or document in Preview and open up the sidebar.

If you drag a new document into the sidebar and drop it in a blank region you will see that appear in the viewing window. But this has not added this page to the first. Preview is simply allowing you to view two separate documents.

To combine pages, drag and drop the second page on top of the first. The second page will appear as thumbnail in the sidebar below the first AND the two pages will appear in the same document in the main viewing window.

This is confusing as both scenarios look the same in the sidebar. You can see the true document structure in the sidebar by picking one of the pages and moving it slightly as though you were reordering it. All pages in the same document will become surrounded with a border and shaded background.

You can reorder pages within a document by dragging and dropping as needed and 'Save As' will save the merged document as a single file.

It is a great feature of Preview but the user interface means that it is effectively hidden unless you know about it.



 

Archive of Tips