About rand9 Technologies

BJ Neilsen

rand9 is the brainchild of BJ Neilsen; Software Developer, Designer, Outdoor Enthusiast, Husband, and Father of two. Hi.

I love to focus on creating and deploying complex web systems. The internet has been my canvas for over a decade. I'm constantly refining development practices to implement smart, fast, and efficient solutions. I excel at building software that brings the right experience to the customer.

While the majority of my career focus has been on the web platform, recent projects have taken me into the mobile development arena, most notably for the iPhone platform. For an exhaustive look at my technical DNA, please refer to my résumè .

And no, I don't tweet .

# Intersecting arrays in Ruby

Just found a slightly satisfying approach to checking the contents of an array in ruby.

I like using Array#include? to figure out whether or not my given array has a certain entry. Unfortunately, if you want to check if an array has a set of possible values, such as, does it contain :a or :b, you can't just pass an array of those values. Let me show you what I mean:

                food = [:milk, :bread, :butter]
                food1 = [[:milk, :bread], :butter]
                expected = [:milk, :bread]
                food.include?(:milk) # => true
                food.include?(expected) # => false
                food1.include?(expected) # => true
                

In other words, include? is very specific about the way it does the matching. But what if I want food.include?(expected) to tell me if food has any of expected's values? Enter Array#&. It doesn't make include? do anything different, but does give us a simple way to get this newer behavior:

                food = [:milk, :bread, :butter]
                expected = [:milk, :bread]
                (food & expected).size > 0 # => true
                

Array#& gets the intersection of two arrays (the values that are present in both) and returns a new array containing only those values. You could add this to any Array instance by simply defining your own include_any? method:

                # myapp/lib/ext/array.rb
                class Array
                  def include_any? values
                    (self & values).size > 0
                  end
                  
                  def include_all? values
                    (self & values).size == values.size
                  end
                end
                
                [:milk, :bread, :butter].include_any?([:milk, :butter]) # => true
                [:milk, :bread, :butter].include_all?([:milk, :butter]) # => false
                [:milk, :bread, :butter].include_all?([:milk, :butter, :bread]) # => true
                

I cheated and gave you an include_all? method also, which just ensures that all of the expected values are present.

I could've used Enumerable#any? but then we'd have to use a block and still use Array#include?. This way, we're golden.

What cool things have you done with ruby today?

· · ·

Post your comment

# Hooking instance methods in Ruby

Everyone and their dog is familiar with ActiveRecord-style callbacks, you know, the kind where you specify you want a particular method or proc to be run before or after a given event on your model. It helps you enforce the principles of code ownership while making it trivial to do the hardwiring, ensuring that code owned by the model is also managed by the model.

I love this kind of programming and recently found that I needed some similar functionality in a particular class, one that wasn't tied to Active[Insert your railtie here]. My case was different in that I knew that any class inheriting from a particular base, which we'll call HookBase, needed a hardwired hook for every method defined, functionality that needed to run for virtually every instance method call. The following example illustrates my need:

                class HookBase
                  def hardwired_hook
                    # functionality every method needs
                  end
                end
                
                class MyClass < HookBase
                  def find_widget
                    # needs setup/teardown help from HookBase
                  end
                end
                

So, operating from the idea that every instance method extending classes implement should have default wrap-around behavior, I got to work. First off, you need to know that ruby has built-in lifecycle hooks on your classes, objects, and modules. Things like included and extended and method_added help you hook in to your code to ensure that the appropriate things are happening on your classes, objects, and modules. So in my case, I needed to know when a method was added to HookBase (or one of its children) so that I could appropriately tap into that code.

method_added is where the meat of the solution lies. When a method is added, ruby fires the method_added call on the object (if any exists), passing it the name of the new method. Keep in mind that this happens after the method has already been created, which is crucial to this solution. We'll next create a new name from the old name, prepended with some identifier (in this case we chose "hide_").

We'll need to check the private_instance_methods array for already defined method names to ensure we're not duplicating our effort (or clobbering someone elses), as well as checking our own array constant for methods we don't want to hook. Remember that method_added will be called on every method that is found for HookBase as well as children. I found that there were HookBase methods I had implemented that were supporting this behavior and didn't need to be hardwired, so I added this to my list of methods to ignore.

If we've made it this far, go ahead and alias the old method to the new one, then privatize the new one. Now we can safely redefine the old method without destroying the code it contained. We also now know that no one (except self) can invoke the private method directly, they'll have to implicitly go through the HookBase first.

Redefining the old method is as simple as using define_method and calling our hardwired_hook method within, passing our new_method (which is privatized), and the old method (for convenience), and any associated arguments and blocks.

The final implementation looks something like this:

                class HookBase
                  class << self
                    NON_HOOK_METHODS = %w( hardwired_hook some_other_method )
                
                    def method_added old
                      new_method = :"hide_#{old}"
                      return if (private_instance_methods & [old, new_method]).size > 0 or old =~ /^hide_/ or NON_HOOK_METHODS.include?(old.to_s)
                
                      alias_method new_method, old
                      private new_method
                
                      define_method old do |*args, &block|
                        hardwired_hook new_method.to_sym, old.to_sym, *args, &block
                      end
                    end
                  end
                  
                private
                  
                  # Hardwired handler for all method calls
                  def hardwired_hook new_method, old_method, args*, &block
                    # perform any before actions
                    puts 'doing stuff before method call...'
                    
                    # Invoke the privatized method
                    __send__ new_method, *args, &block
                    
                    # perform any after actions
                    puts 'doing stuff after the method call...'
                  end
                end
                
                class MyClass < HookBase
                  def find_widget
                    puts 'finding widget...'
                  end
                end
                
                MyClass.new.find_widget
                # doing any before actions
                # finding widget...
                # doing any after actions
                

The great thing about this approach is you may not even care about hardwiring anything, but just want to provide hooking functionality. If that's the case, simply define a class method in HookBase to register a hook (such as before or after), optionally accepting an :only or :except list of methods. Internally store the blocks passed and invoke them in the hardwired_hook method either before or after the method call.

Let me know if you have any comments or different approaches. Happy hacking!

UPDATE: Forgot that method_added needs to be defined in class << self to work properly. Also updated to use the Array#& intersection method I described in Intersecting arrays in ruby instead of using Array#include?.

· · ·

Post your comment

# Paper Skater

How unbelievably sick is this video. I love this.

Skateboardanimation from Tilles Singer on Vimeo.

· · ·

Post your comment