Tuesday, August 28, 2012

Adding find_and_modify to MongoMapper and the simplicity of plugins

I've been using MongoMapper as my ORM for a while now, but for some reason find_and_modify() is conspicuously absent. find_and_modify is important for any situation in which you want to lock a record while you work with it, say by marking a state property

So I worked up a little MongoMapper pluggin that did the trick:



Then to use it, simply, add the plugin to your document model:


class FindAndModifyTest
   include MongoMapper::Document
   plugin FindAndModifyPlugin
end

Here's an rspec test that shows how it works:





VoilĂ 

Kevin



Thursday, August 23, 2012

Rails: When should I override in a subclass or override in the original class?

Despite the typical enormous flexibility of Rails functions, sometimes I find a method that is not quite flexible enough. One has several options:

  1. Write a wrapper that calls the original function.
  2. Write a completely separate implementation.
  3. Override the method in a subclass (this can call the super, so it's a bit like #1)
  4. Override the method in the original class by reopening the class. 
Here's a concrete example:

I was implementing an API authorization token based on the description in the rails cast: #352: Securing an API. This is to avoid #5 in the top 10 security threats facing web applications.

Since my API is used for sending and receiving data from a client web application (based on EmberJS), I wanted to send an API key with each main page load, and then all subsequent Ajax calls would use this key. All this happens behind the scenes. 

But I ran into a problem. How am I to send the API key in the web page served by my test suite (Jasminerice)? 

I'd prefer to not muck with the Jasminerice source code as this will make it a pain to upgrade each new release. In stead I decided to use a helper that Jasminerice was already using, and just provide a new implementation of the built in crsf_meta_tags helper, which could also serve my API's crsf-token in addition to the built in one Rails uses. 

This required #4 from the above list, overriding the method in the original class. This is necessary for Jasminerice to use my implementation. #1 and #2 don't work because Jasminerice won't call a method it doesn't know about. #3 won't work because Jasminerice won't have the subclass in its scope (say I put it in my own ApplicationHelper class, which would work for my local rails app, but not inside Jasminerice). 

That left me with overriding the original implementation. Here's my code:

module ActionView
  module Helpers
    module CsrfHelper
      alias_method :orig_csrf_meta_tags, :csrf_meta_tags
      # I override this function so that I can add my 
      # json_csrf_token tag as well
      def csrf_meta_tags
        api_key = Rack::Utils.escape_html ApiKey.create.access_token
        json_tag = ""
        [orig_csrf_meta_tags, json_tag].join("\n").html_safe
      end
    end
  end
end

In the above, I approximated a wrapper by aliasing the original method and then invoking it, adding my own key to the mix. 

I would only recommend approach #4 when one doesn't have access to or doesn't want to modify some code that uses the function for which a substitute implementation is desired. 

There is one main drawback though. Any other code that relies on the original implementation will break (it won't be possible for only some components to use the new implementation). 

Side note:

Another idea I had was to somehow customize the Jasminerice behavior through its Railtie configuration. Although I wasn't able to find a way to do this. If anyone has suggestions, I'd be interested to here. 

That's it for now.

Kevin

Sunday, August 12, 2012

Testing private methods using singleton methods

I generally use rspec for Ruby unit tests. However, at first glance, it seems that good test coverage is in conflict with good encapsulation. Specifically, private methods cannot be directly tested without some additional thought.

One strategy that is widely advocated is to only test private methods indirectly, through their use by public methods. While perfectly valid, this approach may let use cases slip through the cracks. For example, it may not always be feasible to use the public methods to test all the uses of the private method that one may want to test. This is actually the reason for unit tests in the first place, because not all use cases and exceptions can be uncovered by higher-level interaction (i.e., using the application, integration tests, etc.)

Another strategy is to put all the private methods in a module and include them. However, this means your code gets scattered in multiple places, and that module may not have any other use outside of the one class.

Enter instance_eval

With instance_eval, one can directly call the private method as follows:

obj.instance_eval{ my_private_method }.should 

VoilĂ .

Perhaps one rule of thumb is to use instance_eval sparingly, and only in unit tests (never in integration tests). 

For more discussion on this topic (and a debate about whether private methods should be tested), see this StackOverflow post.

Kevin