Fork me on GitHub

December 14, 2010

Changing RVM's path

Post moved to http://log2.kares.org/post/59891243691/changing-rvms-path

One of the coolest things proving exponential awesomeness of the ruby ecosystem is the Ruby Version Manager (RVM). If You're doing some rubyism and You're not using RVM, You really should - it's worth installing, even if You're happily stuck with Your ruby of choice and You don't really care about all the rubies out there. For example: Gemsets allow You to have different gem setups within the same ruby installation, saving Your butt from a dependency hell.

The recommended installation choice is to curl it down and adjust .bash_profile to load RVM into the shell. Anyways, one probably ends up with RVM living happily under $HOME/.rvm.

Well, if You'd like to keep Your $HOME RVM free or simply just move the install directory to another location, while keeping all the ruby and gem assets You've managed to install over the time, here's a few steps to follow changing Your $rvm_path :



NOTE: Actually my rvm install ree step failed with a "No such file or directory - (Errno::ENOENT)" but looking at the install log revealed no fatal issues (it did fail during the "useful libraries" installation which I do not care about as all my gemsets are working and are full of useful libraries already :)) ...

Now, be happy © RVM !

October 29, 2010

Configuring Factory Girl Correctly

Post moved to http://log2.kares.org/post/59891243027/configuring-factory-girl-correctly

Factory Girl is a great fixture replacement from thoughtbot. However, sometimes a portion of ugliness might spoil the picture e.g. when the gem is not correctly setup with Bundler (at least in Rails 2.3). A typical gem 'factory_girl' setup seems to be working fine but only until You run some database related tasks such as rake db:reset RAILS_ENV=test. Here's what You might end up with :

Mysql::Error: Table 'SomeApp_test.users' doesn't exist: SHOW FIELDS FROM `users`

This is being caused by the gem initialization hook for Rails, executing Factory.find_definitions while the database is in an inconsistent state.

Seems we'll need to get back to the good old days of require it yourself. But adding a require 'factory_girl' in a test helper is not enough. We need to make sure that the factory definitions are resolved (the initializaiton hook might not execute as the Rails.configuration probably already finished initializing while we're loading factory_girl from a test_helper) :

August 28, 2010

Simple Captcha without RMagick

Post moved to http://log2.kares.org/post/59891241725/simple-captcha-without-rmagick

Simple Captcha is as it's name points out is probably the simplest captcha plugin out there. It's a little old and not really updated these days (although there is some SimpleCaptcha3 activity) but still working as expected, at least on Rails 2.

Now, I know there's creatures among us developers who don't really prefer RMagick, which is the core brick of the plugin. Some popular image related "magick" plugins give us alternative options, probably the most common RMagick replacement being MiniMagick. Besides the usual reasons against RMagick I do found one crucial to be JRuby compatibility. There's an attempt to fix this called RMagick4J but it seems to be incomplete (at least for simple captcha it did not play correctly).

Turns out for captcha generation, MiniMagick ain't an option, it misses support for creating images from scratch which is essential. Fortunately, there's still hope thanks to QuickMagick, well that's about enough magick isn't it ?! Sure is, but it's worth it. QuickMagick mixes the simplicity of MiniMagick with the flexibility of RMagick (and works with JRuby).

Enough chit-chat, here's how to enjoy the simplest captcha plugin for Rails without RMagick :



The updated plugin lives at http://github.com/kares/simple_captcha.

UPDATE: The latest plugin version now works on Rails 3.0.0+ !

July 20, 2010

Disabling Test Fixtures

Post moved to http://log2.kares.org/post/59891239111/disabling-test-fixtures

Once upon a time in a west land of Fixtures lived a doubtful engineer. Luckily for him, he was a believer and believed the right way of doing things was chosen by the wiser. He followed the graceful path for a long time, long enough to get lost and realize how nasty things were. Until suddenly one day he knew he can't handle it anymore. And that was the beginning of the obligatory end of Fixtures as we know it ...

When You're a newbie into Ruby on Rails, there's a lot of knowledge "distractions" and it takes a while, even for a experienced developer to form a sober opinion. Rails advocates testing and provides fixtures as a source of test data. I did find this approach misleading. As Your tests grow managing the test data become hard. Having shared test data might be very reasonable for integration tests, but in functional and especially in unit tests the test data might turn out difficult to manage cause of all the corner cases to be tested.

There are testing practices and patterns for overcoming fixtures, but what if You have an existing code base and start migrating slowly towards non-fixture dependent tests. If You decide to go far enough and disconnect Your unit tests from the database and use mocking extensively - good for You, the old tests might happily live with the new ones. If You're like me and create the test data required as part of the test similar to the data factory approach, You might get surprised from time to time. The existing fixtures data (required for the "old" tests) might still be there loaded in the database and might interfere with the "new" data. It would be best if we could disable Rails test fixtures per test. Turns out we can, thanks to my disable_test_fixtures plugin. Here's a gist of using it:



And all the Fixtures developers lived happily ever after by the golden rule of testing: "An imperfect test today is better than a perfect test someday".

May 5, 2010

My Today went Yesterday

Post moved to http://log2.kares.org/post/59891237855/my-today-went-yesterday

It really did, making me unproductive around midnight as some of my unit test started failing. To be honest, I did fall asleep most of the times just by counting the failed assertions.

Now when a Rails test starts failing at a particular time during the day, there's probably some Time.zone misuse. But first let's do a recap here.
Testing time sensitive models or any time related behavior will sooner or later bend us to use Time.now. There's nothing wrong with that, as long as we keep in mind that when a model with a Time attribute value is saved and re-read there's a high chance it won't equal to the initial Time instance set. Most database vendor :datetime columns only use second precision and thus our time looses it's microsecond precision. Easy help, just use a custom time equality asserter:



However, this is not the only difference, after setting and reading the time attribute it holds a ActiveSupport::TimeWithZone instance. Rails performs this "conversion" to enable representing times in any time zone, as the standard Time is limited to UTC and the system zone. Well of course such times are equal no matter of the time zone. Issues might arise when times in different zones are converted to dates.
This starts to happen if You've configured ActiveRecord to store times in UTC (instead of the local time) which I do found very reasonable, as well as setting Time.zone to default to UTC (and adjusting it per request). For example, if You're GMT+0200 positive and write Time.now to an attribute, read it and convert to a Date object, it will start to return yesterday around midnight:


>> t1 = Time.parse "Tue May 04 00:00:00 +0200 2010"
=> Tue May 04 00:00:00 +0200 2010
>> t2 = t1.in_time_zone 'UTC'
=> Mon, 03 May 2010 22:00:00 UTC +00:00
>> t1.class
=> Time
>> t2.class
=> ActiveSupport::TimeWithZone
>> t1.to_date
=> Tue, 04 May 2010
>> t2.to_date
=> Mon, 03 May 2010

Here t2 is "simulating" the ActiveRecord conversion mechanism. Once we realize all that the test failures might be avoided by setting the Time.zone to your local time during tests:



And all the tests lived happily ever after ...

February 24, 2010

Groovy Globbing

Post moved to http://log2.kares.org/post/59891235623/groovy-globbing

Having Java as a first language, it always felt like dynamic languages are closer to the filesystem. Maybe it's cause there's only the bare minimal java.io.File in the standard Java API. In Ruby, for example, there's a bunch of shell-like methods in the FileUtils module, provided as a part of the language core.
Though maybe I shouldn't compare apples with oranges, so I'll get less javish and more groovier. Luckily, I've had a chance of going from Groovy to Ruby and back again. Retrospectively I must say I enjoyed and still enjoy both, but sometimes I miss a feature available in another.
Probably one of the most used methods, and besides my personal favorite, when it comes to matching files is Ruby's Dir.glob. I was truly missing it. To be fair Groovy has a bunch of File additions that come handy. There's eachFileMatch and eachFileRecurse, besides AntBuilder is in the pocket. Yet even the 3 Princes (Perl, Python and PHP) are all "globbing" positive, Groovy should definitely not stand out the row !

A cca. 100 lines later, here it is: a File.glob implemented in (and for) Groovy.

The code stinks after Java and is a bit long for a method (and probably too long for a closure), that's cause my 2 side goals. At first make it easily portable to plain Java in-case I need it someday, thus I avoided Groovy's File extensions. Second, have no "external" dependencies (e.g. helper methods) which made the resulting code less readable but certainly more "embeddable" for the extremely popular CPP (Copy & Paste Programming).

Now, it's useless to show the code (it's dam ugly anyway) but I'll end with a simple example (for those who have not yet discovered the power of globbing) plus a few lines of documentation inspired by rubydoc :



/**
 * Returns filenames found by expanding the passed pattern which is String or
 * a List of patterns.
 * NOTE: that this pattern is not a regexp (it’s closer to a shell glob).
 * NOTE: that case sensitivity depends on your system.
 * 
 *   *                 Matches any file. Can be restricted by other values in
 *                     the glob pattern (same as .* in regexp).
 *                      *  will match all files,
 *                      c*  will match all files beginning with c,
 *                      *c  will match all files ending with c.
 * 
 *   **                Matches directories recursively.
 *
 *   ?                 Matches any one character. Equivalent to . in a regular 
 *                     expression.
 *
 *   [set]             Matches any one character in set. Behaves like character
 *                     sets in regex, including negation ([^a-z]).
 *                     
 *   {p,q}             Matches either literal p or literal q. Matching literals
 *                     may be more than one character in length. More than two
 *                     literals may be specified. Same as alternation in regexp.
 *
 * NOTE: when matching special characters an escape is required, for example :
 * "\\*" or "\\\\".
 *
 * NOTE: flags (e.g. case insensitive matching) are not supported.
 *
 * @see http://ruby-doc.org/core/classes/Dir.html
 * @see http://www.faqs.org/docs/abs/HTML/globbingref.html
 * @author Karol Bucek
 */


BTW, globbing is a built-in feature of decent command interpreters like bash, try ls **/*.txt next time.

January 17, 2010

The Maven Plugin War

Post moved to http://log2.kares.org/post/59891232930/the-maven-plugin-war

I guess, everyone who did a project beyond "Hello World" in maven feels the same - it's a love/hate relationship. To be fair most of the times it's all those battles with the plugins that You need to fight.

This particular one is all about the maven-war-plugin. The war plugin is another of those often betas and it's better that way, otherwise we could actually blame it !
Let's suppose You would like to package Your webapp but just before making the war You would like to change a thing or two. Doesn't matter what, but to explain let's say You would like to change a web.xml context parameter value (e.g. for a production environment). And here's the "impossible" requirement: You can't use maven filtering, the default web.xml with all it's glory have to stay the way it is (usable for deployment out of the box).

The first thing that a maven ninja would think of is to bind to a phase where the project is already pre-packaged to make the changes required and then let the war plugin finish it's packaging work. Now days You can't - the war packaging all happens in a single phase. Feels wrong, but whatever, let's take a closer look by digging into the plugin. There's an interesting aspect of how resources are handled. If web resource directories are specified and they contain the same file the first one found will be packaged. In other words when the plugin copies a resource to be included in the archive it checks if it's already there and if so it skips the file. And luckily web resources are handled before the war source directory.

To demonstrate this concept, let's face a concrete requirement. Suppose we have a web application descriptor similar to this one :



And would like to have the SOME_PORT parameter value changed to a configured value in a production profile.

We'll use gmaven plugin for the job, without more chit-chat here's the POM :



Notice how a resource directory is configured in the profile, that's the directory that will contain the updated web.xml with SOME_PORT changed to 80. Of course the directory does not exist, it's the gmaven goal that will create it during the generate-resources phase. The war goal will run after - during the package phase.

To be complete here's the referenced script that creates the resource dir and the updated web.xml (should be placed inside the project's base directory) :



The groovy code should be self explanatory. The only snag for first time users of gmaven might be the project, ant and log references, these are setup by the plugin as hooks to the maven runtime. See the documentation for more information.

I hope I made the point, a similar setup is usable for changing the content of any resource before packaging. Sure it feels like reinventing the wheel, hopefully maven 3 will get more flexible. Until than for the next project I'll definitely try out gradle or buildr, depending on which leg I get out of the bed that morning.