Seemingly along with the vast majority of other web developers, I’m in the midst of a few projects developed in Ruby, based on and using Rails. This is one bandwagon I’m happy to jump on, and so far much of the hyperbole seems deserved.
I spent quite a bit of time today working out how I could use Ruby’s mixins to dynamically populate my objects with methods based on a user’s role within my application. I have a controller that I want both vendors and admins to be able to use, but I want each of them to be able to access a different set of methods, often with the same names. Rather than implement checks in each method, or even using callbacks to dispatch appropriately, I wondered if my main controller could simply mixin the methods it needed at runtime.
Ruby’s ‘include’ statement won’t work within a method in an existing class, so using it directly from my if statement wasn’t an option, and for some reason I have yet to fathom, Rails wouldn’t play well with my attempts to use the extend statement instead. Eventually I stumbled across the Class#class_eval method and seem to have a working system:
if @user.instance_of? Vendor require 'supplier_vendor' self.class.class_eval('include SupplierVendor') else require 'supplier_admin' self.class.class_eval('include SupplierAdmin') end
I’ve yet to check whether my garbage is properly cleaned up or whether this approach simply clutters the internals, and I’ll be interested to see how the performance compares with using callbacks for dispatching, but its a nice compact option and typical of the succinct options available in Ruby.