zobie's blog I create software, I like music, and I'm mildly(?) OCD.

17Jul/09

Installing RMagick on Ubuntu 9.04 (Jaunty)

Installing the RMagick gem can be a huge headache. Reading the HOWTO on the RMagick site is enough to make anyone nervous. Thankfully the process is much easier on ubuntu however; you only need three commands.

DISCLAIMER: I've only tested this on Ubuntu 9.04 (Jaunty) server.

$ sudo aptitude install -y imagemagick
$ sudo aptitude install -y libmagick9-dev
$ sudo gem install rmagick

And you're done! You can verify the installation using this irb command, taken from the RMagick HOWTO:

$ sudo irb -rubygems -r RMagick
irb(main):001:0> puts Magick::Long_version
This is RMagick 2.10.0 ($Date: 2009/06/19 22:07:05 $) Copyright (C) 2009 by Timothy P. Hunter
Built with ImageMagick 6.4.5 2009-06-04 Q16 OpenMP http://www.imagemagick.org
Built for ruby 1.8.7
Web page: http://rmagick.rubyforge.org
Email: rmagick@rubyforge.org
=> nil
16Feb/09

Web Development Environment

During 2008 I spent most of my time doing web development. There was some Java, PHP and Python, but most of my time was spent working in Ruby on Rails. Rails is a lot of fun and (I know this sounds cheesy, but...) it helped me to enjoy doing web development again.

When I'm working in Java I always prefer to use JetBrains' excellent IntelliJ IDEA. However, this past year I didn't have a license for IntelliJ. I tried every free IDE I could find and wound up choosing Eclipse. I've used Eclipse periodically over the last several years. I don't really like it but I dislike it less than the other free alternatives.

My work was completely server-side and didn't involve developing a database component. Most of my development was done on OS X but I was deploying to Ubuntu so I did work there also. I used maven to build, test and deploy. I'm not a unit-test fanatic but, in this case unit testing was invaluable.

Java Development

My setup for both PHP and Python is the same. When I'm working on Mac I use either TextMate or vim. I haven't done a great deal of Python work but over the past several years I've tried to find a PHP IDE that I like... I'm still looking.

PHP Development

I started out doing my Ruby work using TextMate and Terminal.app. I didn't have any major complaints. There are some nice plugins and various tricks that are handy. But personally, I prefer an IDE. I've heard some people say that IDEs make us lazy. Ok, I'm lazy. But I'm also far more productive when I have a good IDE. When JetBrains started issung beta releases of RubyMine, TextMate was history!

RubyMine's GUI for easily stepping through code in the debugger is great. The inline code analysis is nice for quickly catching typos and the code completion can be useful too. But for me, the best part about having RubyMine is the navigation and documentation.

When I'm working with other developers (or even with frameworks that I didn't write), I don't always know exactly what a method does. Being able to instantly bring up documentation is awesome! If I need more information, I hate wasting time trying to hunt down a method buried in code that I am not familiar with. With one key-stroke RubyMine takes me to the code I'm looking for.

Rails Development

I am definitely a fan of JetBrains' production. IntelliJ is awesome, RubyMine is awesome, and VisualStudio is just broken without ReSharper. There is certainly a learning curve to these tools but once you've memorized the key strokes, the code you need is always right in front of you. And the best part part is that the key bindings are the same across each of JetBrain's products!

One last application that deserves to be mentioned is Navicat. Navicat is by far the best application that I've found for working with MySQL or PostgreSQL. Unfortunately, that's not saying much. I have spent a lot of time using SQL Server and Microsoft's related tools and, as far as I can tell, there is nothing for MySQL that is even in the same league.

Don't misunderstand me. Navicat is a great tool. Allowing me to save connections to different servers with many different login credentials is a lifesaver, especially the ability to tunnel the connections over ssh. Being able to do basic server management via a GUI is nice too. But when I need to design a database, I always turn back to SQL Server Management Studio.

1Jan/09

Read-only Models in ActiveRecord

I recently worked on a project that was built around several hundred GB of data. Several large databases were populated by one team and then consumed by several other applications.

The project I was working on needed to access that data but would never need to modify it. Perhaps I was being overly paranoid, but I wanted to specify that everything from those databases was read-only to make sure nothing was accidently changed.

ActiveRecord is one of the coolest things about rails. With almost no work I get data models, including dead-simple CRUD, in my applications. But the inability to designate a model as being read-only is really frustrating to me.

I know that rails can mark individual instances with :readonly, but I wanted to ensure that every instance of these objects was read-only. Here's what I came up with:

class FooBar < ActiveRecord::Base
  # Prevent creation of new records and modification to existing records
  def readonly?
    return true
  end
 
  # Prevent objects from being destroyed
  def before_destroy
    raise ActiveRecord::ReadOnlyRecord
  end
end

And that's all there is to it! FooBar objects are now read-only.

# You will not be able to create new records
>> fb = FooBar.create(:name => "zork")
ActiveRecord::ReadOnlyRecord: ActiveRecord::ReadOnlyRecord
 
# You will not be able to save modified records
>> fb = FooBar.find(:first)
>> fb.name = "plugh"
>> fb.save
ActiveRecord::ReadOnlyRecord: ActiveRecord::ReadOnlyRecord
 
# You will not be able to destroy existing records
>> fb = FooBar.find(:first)
>> fb.destroy
ActiveRecord::ReadOnlyRecord: ActiveRecord::ReadOnlyRecord

For the sake of simplicity the code here is in a regular rails model. But if you're working with a large number of models like I was, you might consider extracting these methods into a new class "ReadOnlyActiveRecord" which can then used as the parent for the other models. DRY, right?

Depending on your situation, you may need to lock down the record more tightly. With this code you could still create and manipulate new FooBar objects in your code. The exception isn't thrown until you try to persist to the database.

I certainly don't consider myself an expert on rails. If anyone knows a better solution to this problem I'd love to hear it.

20Nov/08

Testing Routes in Rails

Routes in rails are really cool but they can be confusing to newbies and, as they become more complex, it can be difficult to make sure that all of your paths are still working like you expect. My intention here is not to provide a primer on routes but rather to show how easy it is to test and verify routes.

As you define new routes it is important to write tests to validate url formats. You need tests to verify that urls are mapped to the right controller and action:

assert_generates("/directory/stations",
                 :controller => "dashboard",
                 :action => "directory_stations")

And you need tests to verify that controller/action combinations can be correctly mapped back to a url:

assert_recognizes({ :controller => "dashboard",
                    :action => "directory_stations" },
                  "/directory/stations")

The console is your friend when you are trying to test or debug a tricky mapping. Launch the console and, to save some typing, assign a local variable:

$ script/console
>> r = ActionController::Routing::Routes

If you want to see currently defined routes:

>> puts r.routes
ANY /:controller/:action/:id/ {}
ANY /:controller/:action/:id.:format/ {}
=> nil

The first part of the output tells you what HTTP verb the routing applies to, ANY in this case. Other possible values are GET, POST, HEAD, etc. The next element in the output is the pattern that matches the route. The empty braces show that we don't have any of the optional parameters defined that might modify the behavior of the route.

To verify that urls are mapped to the right controller and action use recognize_path:

>> r.recognize_path "/station/index/42.html"
=> {:controller=>"station", :action=>"index", :format=>"html", :id=>"42"}
>> r.recognize_path "/station/index/42"
=> {:controller=>"station", :action=>"index", :id=>"42"}
>> r.recognize_path "/station/index"
=> {:controller=>"station", :action=>"index"}
>> r.recognize_path "/station"
=> {:controller=>"station", :action=>"index"}

To verify that controller/action/id/etc. combinations correctly map back to a url:

>> r.generate :controller => :station
/station
=> nil
>> r.generate :controller => :station, :action=> :index
/station
=> nil
>> r.generate :controller => :station, :action=> :index, :id=>42
/station/index/42
=> nil
>> r.generate :controller => :station, :action=> :index, :id=>42, :param => "xyzzy"
/station/index/42?param=xyzzy
=> nil