Ruby delegate.rb secrets

You've seen SimpleDelegator in action and used it a bit yourself. The delegate library is more than just a fancy method_missing wrapper.

Easy Wrappers

First and foremost, SimpleDelegator is a fancy method_missing wrapper. I know I said the library was more than that, just bear with me.

Here's some sample code:

jim = Person.new # some object

class Displayer < SimpleDelegator
  def name_with_location
    "#{__getobj__.name} of #{__getobj__.city}"
  end
end

displayer = Displayer.new(jim)

puts displayer.name_with_location #=> "Jim of Some City"

That Displayer class initializes with an object and automatically sets it as @delegate_sd_obj. You'll also get both a __getobj__ and a __setobj__ method to handle the assignment of the @delegate_sd_obj.

You may want to alias those methods so they won't be so ugly when you use them: alias_method :object, :__getobj__.

Method Missing

Here's an expanded view of how it handles method_missing:

target = self.__getobj__ # Get the target object
if target.respond_to?(the_missing_method)
  target.__send__(the_missing_method, *arguments, &block)
else
  super
end

The actual code is a bit more compact than that, but it's that simple. SimpleDelegator is so simple, in fact, that you can create your own implementation just like this:

class MyWrapper
  def initialize(target)
    @target = target
  end
  attr_reader :target

  def method_missing(method_name, *args, &block)
    target.respond_to?(method_name) ? target.__send__(method_name, *args, &block) : super
  end
end

That's not everything, but if all you need is simple use of method_missing, this is how it works.

SimpleDelegator Methods

SimpleDelegator adds some convenient ways to see what methods are available. For example, if we have our jim object wrapped by displayer, what can we do with it? Well if we call displayer.methods we'll get back a unique collection of both the object's and wrapper's methods.

Here's what it does:

def methods(all=true)
  __getobj__.methods(all) | super
end

It defines the methods method and uses the union method "|" from Array to make a unique collection. The object's methods are combined with those of the wrapper.

['a','b'] | ['c','b'] #=> ['a','b','c']

The same behavior is implemented for public_methods and protected_methods but not private_methods. Private methods are private, so you probably shouldn't be accessing those from the outside anyway.

Why does it do this? Don't we want to know that the main object and the SimpleDelegator object have methods of the same name?

Not really.

From the outside all we care to know is what messages we can send to an object. If both your main object and your wrapper have methods of the same name, the wrapper will intercept the message and handle it. What you choose to do inside your wrapper is up to you, but all these methods lists need to provide is that the wrapper can receive any of those messages.

Handling clone and dup

SimpleDelegator will also prepare clones and dups for your target object.

def initialize_clone(obj) # :nodoc:
  self.__setobj__(obj.__getobj__.clone)
end
def initialize_dup(obj) # :nodoc:
  self.__setobj__(obj.__getobj__.dup)
end

Read Jon Leighton's post about initialize_clone, initialize_dup and initialize_copy in Ruby for more details about when those methods are called.

Making your own SimpleDelegator

SimpleDelegator actually inherits almost all of this from Delegator. In fact, the only changes that SimpleDelegator makes is 2 convenience methods.

class SimpleDelegator < Delegator
  def __getobj__
    @delegate_sd_obj
  end
  def __setobj__(obj)
    raise ArgumentError, "cannot delegate to self" if self.equal?(obj)
    @delegate_sd_obj = obj
  end
end

Subtracting all the comments around what those methods mean, that's the entirety of the class definition as it is in the standard library. If you prefer to use your own and call it SuperFantasticDelegator, you only need to make these same getter and setter methods and you've got all that you need to replace SimpleDelegator.

Keep in mind, however, that the __setobj__ method has some protection in there against setting the target object to the wrapper itself. You'll need to do that too unless you want to get stuck in an endless method_missing loop.

Using DelegateClass

The delegate library also provides a method called DelegateClass which returns a new class.

Here's how you might use it:

class Tempfile < DelegateClass(File)
  def initialize(basename, tmpdir=Dir::tmpdir)
    @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
    super(@tmpfile)
  end

  # more methods here...
end

This creates a Tempfile class that has all the methods defined on File but it automatically sets up the message forwarding with method_missing.

Inside the DelegateClass method it creates a new class with klass = Class.new(Delegator).

Then it gathers a collection of methods to define on this new class.

methods = superclass.instance_methods
methods -= ::Delegator.public_api
methods -= [:to_s,:inspect,:=~,:!~,:===]

It gets the instance_methods from the superclass and subtracts and methods already in the Delegator.public_api (which is just the public_instance_methods). Then it removes some special string and comparison methods (probably because you'll want to control these yourself and not have any surprises).

Next it opens up the klass that it created and defines all the leftover methods.

klass.module_eval do
  def __getobj__  # :nodoc:
    @delegate_dc_obj
  end
  def __setobj__(obj)  # :nodoc:
    raise ArgumentError, "cannot delegate to self" if self.equal?(obj)
    @delegate_dc_obj = obj
  end
  methods.each do |method|
    define_method(method, Delegator.delegating_block(method))
  end
end

The code is sure to define the __getobj__ and __setobj__ methods so that it will behave like SimpleDelegator. Remember, it's copying methods from Delegator which doesn't define __getobj__ or __setobj__.

What's interesting here is that it's using Delegator.delegating_block(method) to create each of the methods. That delegating_block returns a lambda that is used as the block for the method definition. As it defines each of those methods in the methods collection, it creates a forwarding call to the target object. Here's the equivalent of what each of those methods will do:

target = self.__getobj__
target.__send__(method_name, *arguments, &block)

For every method that it gathers to define on this new DelegateClass it forwards the message to the target object as defined by __getobj__. Pay close attention to that. Remember that I pointed out how you can make your own SimpleDelegator and create your own getter and setter methods? Well DelegateClass creates methods that expect __getobj__ specifically. So if you want to use DelegateClass but don't want to use that method explicitly, you'll need to rely on alias_method to name it something else. All of your automatically defined methods rely on __getobj__.

Lastly, before returning the klass, the public_instance_methods and protected_instance_methods are defined. There's some interesting things going on in those method definitions, but I'll keep the explanation simple for now.

This Tempfile class that we created is actually exactly how the standard library's Tempfile is defined.

If you're not familiar with it, you can use it like this:

require 'tempfile'
file = Tempfile.new('foo')
# then do whatever you need with a tempfile

If you dive into that library you'll see:

class Tempfile < DelegateClass(File)

The tempfile library relies on the delegate library, but not in the way that you might find in the wild. Often I see developers using only the SimpleDelegator class, but as you can see there's a handful of other ways to make use of delegate to handle message forwarding for you.

Ensure nested objects/hashes exist

Recently I was working on someone else's code and found quite a lot of repetition of similar code in their JS files. Here's an example:

if(typeof(flamethrower) === 'undefined'){ flamethrower = {} };
if(typeof(flamethrower.fuel) === 'undefined'){ flamethrower.fuel = {} };
if(typeof(flamethrower.fuel.fire) === 'undefined'){ flamethrower.fuel.fire = {} };

This sort of pattern kept coming up in file after file.

There are 2 things to learn about the project from this code. The first is that there is obviously a loading problem.

The number of files that followed this pattern was a serious indicator that someone either wasn't investigating a load order problem, or that the developer was being overly protective of the code in a particular file to avoid errors. So the first step when encountering this is to investigate dependencies and load order.

But sometimes you may actually need to ensure that some nested structure exists. Your load order may need to be necessarily arbitrary or unpredictable.

To DRY up this code we can write a recursive function and get something as simple as:

app.ensure_struct('flamethrower.fuel.fire')

This makes our code much easier to process and understand. In the first example you see so much code that you are required to slow down and read carefully to ensure you haven't missed anything. A simple typographical error would be very easy to miss and could introduce an unexpected bug.

How can recursion help us here? Let's take a look at the final function first:

var app = {}

app.ensure_struct = function(atts,scope){
  var scope = scope || this;
  if (atts == "") {
      return scope;
  }
  var parts = atts.split('.'),
      first_attribute = parts.shift();

  if (typeof (scope[first_attribute]) === 'undefined') {
      scope[first_attribute] = {};
  }
  app.ensure_struct(parts.join('.'), scope[first_attribute]);
  return scope;
}

We've defined this on an app object but that can be whatever you want. First, what we care about is some string representing the structure that we need. In our example we used "flamethrower.fuel.fire" so that's the first argument that we need to handle.

app.ensure_struct = function(atts){
  var parts = atts.split('.');
}

This gives us an array of parts to turn into objects. We'll also need a starter object to add these items and we can begin to check if they exist or set them.

app.ensure_struct = function(atts){
  var parts = atts.split('.');
  var starter_object = {};

  if(typeof(starter_object[parts[0]]) === 'undefined'){
    starter_object[parts[0]] = {};
  }
}

The problem here is that we have begun by getting the first of the attributes from our array. We still need to address the rest of our attributes. One way to do this would be to loop over the array of parts and add those named objects to the last object we had in hand:

var last_object = starter_object;
var index = 0;
while (index < parts.length) {
  if (typeof (last_object[parts[index]]) === 'undefined') {
    last_object[parts[index]] = {};
  }
  last_object = starter_object[parts[index]];
  index++;
}

You could instead use a for loop to shrink it a bit:

for(var i = 0, o = starter_object, l = parts.length; i < l; i++){
    attribute = parts[i]
    if(typeof(o[attribute]) === 'undefined'){
       o[attribute] = {};
   }
   o = o[attribute];
}

As an alternative, we can use recursion to tackle our needs. This helps simplify the code a bit:

var parts = atts.split('.'),
    first_attribute = parts.shift();

if (typeof (scope[first_attribute]) === 'undefined') {
    scope[first_attribute] = {};
}
app.ensure_struct(parts.join('.'), scope[first_attribute]);

I'm happier with that. Inside our ensure_struct function we reuse what we've already written by joining our leftovers and sending a new to the fuction. Of course, to get this to work we need to change the arguments that the function accepts and check that we haven't sent a blank string in for the attributes. When we hit our last part, the leftover_attributes is an empty array and joining it will return a blank string.

app.ensure_struct = function(atts,scope){
  var scope = scope || this;
  if (atts == "") {
      return scope;
  }
  var parts = atts.split('.'),
      first_attribute = parts.shift();

  if (typeof (scope[first_attribute]) === 'undefined') {
      scope[first_attribute] = {};
  }
  app.ensure_struct(parts.join('.'), scope[first_attribute]);
  return scope;
}

Now, we can set our scope from the outside if we like.

app.ensure_struct('values.one.two', other_object);

And yes, this comes from an actual project named flamethrower.

Searching through your bundled gems

You've probably been working on a project where someone added a feature from a gem which caused an error, but you had no idea where to find the offending code.

For me, that happened yesterday. Someone had removed a database table without diving in to see what code actually required the table. Unfortunately, this is a rescue project which barely has tests.

Here's a quick summary of what you can do:

ag thethingyouneed `bundle show --paths`

I began writing some acceptance tests to cover our asses and found that when I attempted to delete a user, the test blew up. Deleting a user was completely unrelated to what I actually cared about but it coincidentally happened for my test.

The failure was because I was missing a receipts table. The fact that this table was needed was news to me, so I asked other team members to find out what it was.

"Oh, yeah. Have you rebased onto develop? It was removed."

WTF?! Why? Why would anyone remove a table and not make sure to investigate that no leftover code required it? Unfortunately lazy developers make mistakes.

So I began digging. I knew the requirement for the offending table existed somewhere in our project, but there was no direct reference in our application code.

Bundler must have a way to search through it's gems, right? Wrong.

I found a few pull requests related to this need and realized that it was much simpler than relying on bundler to do the job for me.

Bundler can provide you with all the load paths that it creates with

bundle show --paths

And nix tools like grep or ack can take a collection of paths to search through. I really like using the_silver_searcher however, so that's my go-to tool. It's super fast.

All I needed to do was pass that collection of paths to ag and I had what I needed.

ag receipts `bundle show --paths`

Then I was on my way and found that we were using a gem that provided an acts_as_messagable method that expected a receipts table to exist was used in one of our models and was no longer needed.

There are 3 lessons here.

First, you can compose things with unix tools and I don't need Bundler to do the entire job for me.

Second, you really should be writing tests. It's the presence and execution of a test that found this bug for me.

Third, always make sure you properly clean up your project. Consider the impact of your laziness on the rest of the team. An ounce of prevention is worth a pound of cure.

Chubby models are still fat with Concerns. DCI focuses on how things work together

You've seen complicated codebases. You've dug through other people's code without a clue to what's going on or how it all fits together. Perhaps it was your own code or perhaps someone else's but you know how difficult it can be to figure out how this or that aspect of a system implements some required feature.

Often, code organization is a key aspect of aiding communication. Today on the 37signals blog, David Heinemeier Hansson wrote about how ActiveSupport::Concern can really help clean up your code. Rails 4 will even have new concerns directories in the load path by default, making it even easier to use this feature.

He points out that Basecamp has almost 40 concerns that organize features required for multiple models. Giving an example, he says "This concern can then be mixed into all the models that are taggable and you’ll have a single place to update the logic and reason about it."

What's great about this is that single place. To understand something thats "Taggable" or "Searchable" you only need to find that concern and you have all that you need. Making changes is just as easy; it's all right there.

Addressing some of the objections to these fat models, he says:

It’s true that this will lead to a proliferation of methods on some objects, but that has never bothered me. I care about how I interact with my code base through the source. That concerns happen to mix it all together into a big model under the hood is irrelevant to the understanding of the domain model.

I agree with the first part of this. Most of the time an object that has many unrelated methods isn't much of a concern. But when we need to drop into a debugger and look at what the object is and can do, then we are met with far more than we need. Inspecting the runtime object becomes difficult because of the overwhelming features and responsibilities that it has.

Almost 100% of the time, however, we interact with code through the source. This is spot on. We read and write code. But the fact that concerns happen to mix it all together under the hood is not irrelevant to understanding a domain model. It's important how many of these mixins are used and how complicated an individual class can become.

But even more important is how it works. Not how things are mixed in, but how your program works. What is going on?

Why do you care that a model is Taggable? What purpose does it serve and what other actor in the system will have a need for it?

Using concerns can be helpful, but if it's used by many models it may effectively become a fragile base class problem where changes to it have unintended ripple effects through those models that inherit its features.

ActiveSupport::Concerns and Roles in DCI are not the same. Roles in DCI are ONLY defined within a context. Your context represents a use case for your system and is larger than a single procedure. A use case covers success paths, failure paths, and alternate paths to the execution.

I had one reader of Clean Ruby, Drew Ulmer, write to me and say:

As far as putting roles directly into contexts, I can't tell you how much I love this idea. It's fantastic to have all of the logic and model behavior for a specific activity in one place and not have to jump around files. It keeps the models focused around how they are defined and not around what we use them for or how they behave; it keeps the behavior focused and easy to reason about; and it defines a very clear API that must be implemented for a context.

I passed this along to my mailing list and after reading it, I got this response from Anthony Burton saying:

To be honest, reading this I kept thinking "that's just the way things were supposed to be". Nevertheless, I always get so frustrated trying to dig through a project (new or old, right?), and trying to trace the flow of execution and how things fit together. This made me think of a project I worked on a few years back (which thankfully had a substantial logging capability) where I wrote a little perl script that would parse logs files and show how things were linked together. It was a very popular utility with the other devs and I was always curious, 1) why no one had written something like it before me; and 2) why the code wasn't just organized differently.

This is a valuable lesson for communicating what your software is supposed to do. You not only need to read the code, but you need to understand how different pieces work together. DCI is a great way to organize code and achieve better communication.

Here's a dumb example of what your context might look like:

class SwappingDetails
      def initialize(source, recipient)
        @source, @recipient = source.extend(Source), recipient.extend(Recipent)
      end

      def swap
        # trigger the appropriate methods
      end

      def other_trigger
        # trigger alternate behavior
      end

      module Source
        # some related methods here
      end

      module Recipent
        # some related methods here
      end
    end

Those modules represent the methods required for an object playing the role. With concerns, you must understand more about the classes of objects ahead of time whereas within a DCI context you'd focus only on roles and their interaction. When using concerns, you understand less about what will trigger the action, what other objects are necessary, and what roles those other objects play.

Concerns can be useful, but just like anything else they can be done poorly. Thinking in terms of interacting roles is not the same as abstracting related behaviors into a module.

Regardless of what you do in your application, communicating it's purpose is key to managing change. The better others can understand how something works, the easier it will be to make necessary changes.

$15,000 in Income From an eBook, How I Did It

Over less than 6 months I've made more than $15k in revenue from Clean Ruby. It's an unfinished book and I've been working to polish it up and get new content out to my customers but I wanted to take a step back and review where I am.

Grand Plan Gone Wrong

I already had a product idea, I just needed help getting it going. Or so I thought.

I asked Eric Davis, who wrote Refactoring Redmine what he thought of Amy Hoy's 30x500 course. For him, it was an absolutely positive experience and he let me know that when you take it once, you can keep taking it.

I was cautious about the cost of the course, but with that reaction I decided it would be a good investment to finally make my CMS hosting service, Solar System a reality.

When the course began, I was super eager. I already had a leg up because I had most of my product put together. I just needed to figure out how to market it.

And the first thing I learned was that my product was dead, would remain dead, and was a waste of further time and effort. I fundamentally had begun in the wrong place and needed to first find what people wanted.

For me, it was like building a shop in the middle of nowhere. I chose a place that seemed like it would be great for a trainload of customers to pass through. After the course however, I knew how to look for existing tracks first and then listen for the train approaching.

How I Chose My Product

I started with this Recurring Revenue Roundup and wish I had built that product first, given some of the problems I had accepting some people's money in my initial launch.

But I was really distracted from this course by a new idea called DCI. If you're not a programmer, don't worry. It's a new and challenging way of thinking about programming. That's all you really need to know.

I was trying to build my other product, but was instead constantly, and eagerly, distracted by DCI. I read about it. I wrote notes. I tried out simple ideas in code. I started applying what I learned to my daily work. "Damn it!" I thought. I want to build a product but I can't focus on that.

This DCI idea is new. There were practically no places it was being discussed. I thought that would preclude me from using it to make a product. Who cares about it? I have no idea, I can't find them.

I write on my blog from time to time. Not often enough. I planned a blog post because the idea is important and powerful. Someone should be blogging about it.

So I wrote my first post and decided just before I published it that I would add an email sign-up form. http://www.saturnflyer.com/blog/jim/2011/09/28/4-simple-steps-extending-ruby-objects-the-tip-of-the-iceberg-with-dci/

I rarely get comments on my blog. I still don't get many, but within a few short hours I had 0 comments, but 12 people on my mailing list!

WTF!?

Apparently people will give your their email sooner than they will make a comment. I didn't quite do customer research the way she teaches, but I went fishing. Little did I know, but I wrote what Amy calls an E-Bomb (for Education Bomb).

Finding the Ears to Listen

The thing about programmers (aside from the fact that some are strangely offended by that term and prefer "developers") is that they really enjoy technical stuff.

But most people don't do technical stuff because it's there and it's technical. They read, write, and study because it gets them to some greater goal.

That is what Clean Ruby does.

It's not a book about DCI. It's a book that will help you better manage your development effort to reflect your business. It's a book about thinking.

I noticed that despite great developers being great, they often overlook things. There is a lot to consider when developing an application and seemingly small things can fall through the cracks.

I took great inspiration form both Lean Architecture and Clean Code. Both of these books are about thinking too. These aren't books about patterns or code wankery, they teach you to slow down and do things properly.

Encouragement and Support

I'm thankful to have the support of many people. I've been fortunate to have guidance and understanding on programming concepts by Jim Coplien and Trygve Reenskaug. They have been both critical and supportive exactly where I need it. And I've been lucky enough to get a deeper understanding of things like delegation by asking David Ungar and Henry Lieberman directly.

I'd asked Alistair Cockburn for his opinion about my book. In an email I mentioned that "I'm often the developer who spends the most time thinking about method, class, or variable names. And I often take the time to go back and clarify when I've met a misunderstanding somewhere."

He replied with this: "I got in trouble at a small co in 1983 cuz I wrote that way in Radio shack TRS-80 assembler. One of the obscure coders said I was the worst programmer he'd ever seen. Wonder what he's doing with his life these days."

All this and more is leading me to create a book that will be a long-lasting, helpful product. There are plenty of people working on their own products in the 30x500 group who help keep me focused: Noah Gibbs, Brennan Dunn, Alex Korban and more.

Revenue

With all my research, thinking, experimenting, questioning, and daily work going on I've been selling books.

I was very nervous to launch the book. I've never written a book before and I was planning to release it before it was done. I actually chose to do that because I'd gotten pressure from anxious people waiting to become customers.

My pre-launch sales have been fantastic; much better than I expected.

The initial spike of sales was a total surprise to me. I began collecting comments from Twitter about my book and was happy to see my book called "long-awaited".

I was building a product that people wanted. I wasn't wasting time figuring out how to market something that I thought possibly could be useful like my CMS hosting. My book is actively helping developers take a second look at their applications and think harder about the real business value of what they do.

After a tip from my friend Roy Tomeij (who is also writing a helpful book) I gathered comments and relevant info in a story so I wouldn't lose that feedback and encouragement.

After less than 6 months, this is how it looks.

But my sales have dipped as my personal life has been turned upside down. I've gone through the process of buying a new home, having a tree fall on it hours after we signed the deed, had a daughter born a day after that (my 4th child), found mold in the basement and had it removed, found plumbing problems, electrical problems, and finally more mold.

Despite all that, I feel great. I'm now selling a product that doesn't require my time for every dollar. Hourly consulting is great, but it requires hours. Building a product completely removes me from needing to provide hours for money. This is a life-changing experience.

I am eager to get back to my research and finish the book and my customers are eager to get it.

The book has helped getting my name out for my consulting work as well. A broader audience now sees that I know how to help them build software in large systems and how I can train them to do the same. What's great about writing this book is that the small companies and individuals who can't afford that kind of consulting are able to learn from the book for a fraction of what they charge for an hour's worth of work.

Buy Clean Ruby and learn to write Ruby applications that better reflect your business. And let me know what you think.

The Gang of Four is wrong and you don't understand delegation

The Gang of Four got it wrong. Ruby's standard library has it wrong. Rails has it wrong.

Is it still wrong if everyone is doing it?

Yes.

The Gang of Four book Design Patterns gives us common vocabulary to understand basic patterns in Object-oriented programming. It helps all of us use the same terms when discussing our software and prevents confusion.

Sadly, this book seems to cause a whole hell of a lot of confusion.

They say "prefer composition over inheritance." That's great, there's good reason for that.

They say to use "delegation." That's great. Although there's not a single example of delegation in their book.

I do not think it means what you think it means Delegation is a technique often cited as a way to create flexibility in your programs. That is to say, delegation is often given as the way to composition.

But delegation isn't what you think it is. The Gang of Four have lead you astray.

Worse still, almost every reference you'll find for "delegation" shows you examples of just object collaboration with message forwarding. They are examples of plain old method calls and not delegation.

Now imagine what your mentor would say about understanding basic programming concepts...

Don't have a mentor? That's ok. Imagine that you do. Now imagine what your mentor would say about understanding basic programming concepts...

You should probably understand them correctly, right?

So what is Delegation?

Delegation is easy to understand but we're so used to hearing and reading it in reference to something else. Let's fix that.

Henry Lieberman coined the term "delegation" in Using prototypical objects to implement shared behavior in object-oriented systems released with the OOPLSA '86 Conference proceedings on Object-oriented programming systems, languages and applications. That content is behind a pay wall, but you can read similar and updated content on his website

In there, you'll find exactly what delegation is, but I'm not sending you away to pore over another long article; I can simplify it for you. When you have time, however, go read Lieberman's own words.

Lieberman discussed this in terms of a GUI drawing tool. Here's the key idea behind delegation:

When a pen delegates a draw message to a prototypical pen, it is saying "I don't know how to handle the draw message. I'd like you to answer it for me if you can, but if you have any further questions, like what is the value of my x variable, or need anything done, you should come back to me and ask." If the message is delegated further, all questions about the values of variables or requests to reply to messages are all inferred to the object that delegated the message in the first place.

In short, when you send a message to an object, it has a notion of "self" where it can find attributes and other methods. When that object delegates to another, then any reference to "self" always refers to the original message recipient. Always.

The other inheritance

Class-based inheritance isn't the only game in town. Prototype-based inheritance is another way to structure your objects for behavior sharing. One approach sets behaviors in an abstract location (the class) and another sets it on instances (the objects).

Self is a programming language which implements what Lieberman defines. Self has objects which contain slots. Each slot can contain a method, or a reference to a prototype object in a parent slot. If an object received a message it didn't understand, it could delegate to an object in its parent slot.

This is prototypical inheritance, not class inheritance. It is similar, although not the same, as saying that an object has a class (like Ruby objects) which contains additional behavior.

Self giving us objects with a parent slot is he equivalent of JS giving us an object with a prototype reference.

JS is the most popular prototype-based language and is much easier for you to try, so rather than teach you Self, we'll look at JS. You can even open up your browser's console and try this out right now.

In JS we can assign a prototype: the equvalent of the parent slot in Self.

function Container(){};
Container.prototype = new Object();
Container.prototype.announce = function(){ alert("these are my things: " + this.things) };

function Bucket(things){this.things = things};
Bucket.prototype = new Container();

bucket = new Bucket("planes, trains, and automobiles")
bucket.announce() // alerts "these are my things: planes, trains, and automobiles"

In delegation parlance the bucket object is the client which forwards a message to the delegate.

In the above example, you can see that the evaluation of this.things was done in the context of the client object. When we called the announce function, it was found on the delegate object. When the function was evaluated, this refered to the client.

When a JS object's prototype contains a functon, the function is evaluated as if the object has that method. The first example showed that this (which is just self in JS) always referred to the original message recipient.

What about Ruby?

First, understand forwarding. Forwarding is passing a message from one object to another. The Ruby standard library forwardable is aptly named and allows you to forward messages from one object to another.

Now, let's take the poorly named delegate library from the Ruby standard library which also allows you to forward messages from one object to another.

require 'delegate'

# assuming we have a Person class with a name method
person = Person.new(:name => 'Jim')

class Greeter < SimpleDelegator
  def hello
    "Hi! I'm #{name}."
  end
end

greeter = Greeter.new(person)

greeter.hello #=> "Hi! I'm Jim."

What happens inside that Greeter is that when the greeter instance is initialized it contains a reference to the person. When an unknown method is called, it is forwarded to the target object (which is person). Remember, we're still looking at the delegate library, which helps us forward messages... Confused? Yeah, I was too. So, it seems, is the rest of the world.

Forwarding is just the passing of a message to an object: a method call.

The difference between this and delegation is that these libraries allow you to easily forward messages to additional objects, rather than executing the method of another object in the context of the first like we saw with prototype-based inheritance in JS.

We are often barely aware of this because Ruby's method_missing power does the trick in SimpleDelegator. We think about methods automagically going to the object we want.

Even though our Greeter method refers to self, the message is forwarded to the other object and handled there when, of course, the method is missing on the client.

If we want to share behavior without extending an object with additional methods, then method_missing and/or SimpleDelegator can do the trick nicely. This works well for simple uses. It does, however, break references to an object's class.

Suppose, for example, we want to reference the client object's class with some new kind of greeting. And instead of the normal greeting, let's make it say "Hi! I'm the esteemed Person, Jim."

We don't want to completely rewrite the method, so we'll rely on super to get whatever is implemented in the regular Greeter.

class ProperGreeter < Greeter
  def name
    "the esteemed " + self.class.name + ", " + super
  end
end

proper_greeter = ProperGreeter.new(person)

proper_greeter.hello #=> "Hi! I'm the esteemed ProperGreeter, Jim."

Hmmm. That's not what we expected. What we wanted to see was "the esteemed Person".

This is a simple illustration of the fact that we have two objects and is an example of self-schizophrenia in Object-oriented design. Each object has its own identity and notion of self. We can fix that by changing the reference to use __getobj__ (the way SimpleDelegator expects) instead of self, but this is an illustration of how self does not refer to what we want. We must explicitly work with two objects and our mental model always requires that we think about two objects interacting when we only really care about altering the behavior of one.

This is not delegation. This is always two objects collaborating. Despite the numerous books, articles, and software libraries telling you otherwise. The Gang of Four got Delegation wrong, but that's OK because now you know better.

Whatever, I'll call it what I want

Who cares. Let's not rock the boat. Everyone is doing it.

Yeah, Design Patterns showed examples in C++. And C++ can't do delegation. So is that a valid argument for rewriting the meaning of a term?

If the language you use can't provide it, don't just call what the language can do "delegation."

Get the concepts right

Developing an application requires that you understand not only your business domain concepts, but also understand many tools and approaches to your design. Software design patterns are common ways to solve common problems. Understanding what they are and when to use them is a key part of being an efficient developer.

The Design Patterns book is often lauded for giving names to commonly used software design patterns. This helps all of us use the same terms when discussing our software and prevents confusion.

Of course, as I began research for Clean Ruby I picked up the Design Patterns book for some clarity. "Surely this book will help guide the discussion and understanding of how to approach different patterns," I thought. Sadly, it contains a glaring mistake that has been repeated and codified in numerous books, articles, and software libraries. Again and again I've read the same description of a behavior sharing and object composition pattern in software that is almost always given the wrong name.

The Design Patterns book is great for having pushed the idea of "composition over inheritance." In fact, so many developers seem to love this phrase that you'll probably be hit over the head with the term the next time you argue for setting up class-based inheritance. Thankfully, Sandi Metz defends class-based inheritance for its logical purposes in Practical Object Oriented Design in Ruby.

Design Patterns is often praised, not for innovation but, for its consolidation of terms. It guides us in the language that we use to understand and discuss different ways of approaching problems. It named for us common patterns so that we could better communicate with each other about what we are creating.

That praise, however, falls a little flat when you try to understand delegation.

My book, Clean Ruby, dives into understanding delegation and explores ways to keep your projects well origanized, maintainable, and loosly-coupled, giving you ways to share behavior and avoid cognitive overhead. Get it now and get your concepts straight.

How to preserve idioms in Ruby subclassing

Ever wonder why you call new on a class but define initialize? Let's take a look.

Leaning on inheritance is a great way to solve related problems in our applications while allowing for some variation in behavior. Inheritance is simple and easy to implement.

Here's a quick example of where developers often stumble by writing classes that require too much knowledge about their subclasses.

Let's make a simple class that we'll use to say hello:

class Greeter
  def initialize(args)
    @name = args.fetch(:name){ 'nobody' }
  end

  def greet
    "I'm #{@name}."
  end
end

Here we have a Greeter class and when you initialize an object from it you'll be able to tell it to greet with an introduction:

greeter = Greeter.new(:name => 'Jim')
greeter.greet
=> "I'm Jim."

We later find that in some cases we need a variation of this with something more formal. So let's make a class to support that:

class FormalGreeter < Greeter
  def greet
    "I am your servant, #{@name}."
  end
end

With this FormalGreeter class we have a different introduction:

greeter = FormalGreeter.new(:name => 'Jim')
greeter.greet
=> "I am your servant, Jim."

Adding Default Behavior During Initialization

Later you decide that your FormalGreeter really ought to do something special during the greeting.

greeter = FormalGreeter.new(:name => 'Amy', :movement => 'curtsy')
greeter.greet
=> "I am your servant, Amy."
greeter.action
=> "curtsy"

Here our FormalGreeter is the class that will move during the greeting. So we can just define initialize:

class FormalGreeter < Greeter
  def initialize(args)
    @movement = args.fetch(:movement){ 'bow' }
    super
  end

  def action
    @movement.to_s
  end
end

All you have to do for everything else to work is to remember to call super.

But having to remember things can be a stumbling block in your code. Humans forget things.

One way to do this would be to setup a special initialize method to be called in the base class. There you could define your own behavior in the subclasses:

class Greeter
  def initialize(args)
    @name = args.fetch(:name){ 'nobody' }
    special_initialize(args)
  end

  def special_initialize(args)
    # hook for subclass
  end
end

This is better because we don't need to remember in what order we should run our code. Does my code go first and then super? Or do I call super first and then do what I need? Now, we don't need to mentally recall the procedure.

This simplifies our initialization process, but we still have the need to remember that instead of calling super within our initialize method, we need to define our special_initialize method.

Humans forget things.

This should still be easier.

Instead of needing to remember things, you can hook into your initialization in a way that requires less thinking during the development of your subclasses. Fallback to standards like defining initialize.

Here's how you protect idiomatic code:

class Greeter
  def self.new(args)
    instance = allocate # make memory space for a new object
    instance.send(:default_initialize, args)
    instance.send(:initialize, args)
    instance
  end

  def default_initialize(args)
    @name = args.fetch(:name){ 'nobody' }
  end
  private :default_initialize

  def initialize(args)
    # idiomatic hook!
  end
end

Now our subclasses have the benefit of being able to use their own initialize without the need for us to remember super nor a custom method name.

class FormalGreeter < Greeter
  def initialize(args)
    @movement = args.fetch(:movement){ 'bow' }
  end

  def action
    @movement
  end
end

Now you have some insight into the way that Ruby uses your initialize method.

Wroclove.rb Presentation

I was very fortunate to present some ideas to a group of developers in Wroclaw, Poland at http://wrocloverb.com/

Slides always leave out interesting things (and they should) but I'll post the video as soon as it's available.

Triggering the DCI Context

There's been a lot of interest in DCI among Ruby developers, and a lot of good discussion going on among some blogs about application architecture.

I've written about basic information on the concept which touched on some sample code. One main point to make is that our class oriented approach to application architecture is that we end up with junk drawer objects; objects which contain methods for any number of interactions that may be performed at some time during the execution of the application.

Mike Pack's article has been the first to discuss triggers for DCI in Rails (but correct me if I'm wrong). Triggers are the actions that initialize your Context to perform the algorithm.

When you develop your system with DCI one of the goals is to take your business use cases and describe them in your Context. When writing a use case you'll say that you have a specific preconditions, specific actors, and of course specific goals. But we can look to Alistair Cockburn for the full understanding of use cases.

Here are the main points about what a use case should do and some points about how we can apply this to our executable code. In Cockburn's words (with my comments afterward) use cases DO:

Hold Functional Requirements in an easy to read, easy to track text format. We can do this in code. Ruby is widely known for being easy to read and the community values beautiful code. As far as holding functional requirements, that should be very simple for executable code to do.

Represents the goal of an interaction between an actor and the system. The goal represents a meaningful and measurable objective for the actor. This is both an important aspect of your business, and an important aspect of DCI. When we're attempting to achieve our business goals, we should write software that is uniquely designed to do that. The Context is an object that encapsulates this concept.

Records a set of paths (scenarios) that traverse an actor from a trigger event (start of the use case) to the goal (success scenarios). In simple code this is easy enough to do with if/else blocks or case statements, for example.

Records a set of scenarios that traverse an actor from a trigger event toward a goal but fall short of the goal (failure scenarios). An example here might be the above if/else blocks or perhaps a rescue from an exception. A use case describes a complete interaction between the user and your system and it is the responsibility of your Context to implement this.

Are multi-level: one use case can use/extent the functionality of another. This is reflected in DCI in the fact that we want to achieve the vision of Alan Kay, to create a network of interacting objects much like biological cells or computer networks. A Context can trigger other Contexts within.

What you're attempting to do with DCI is not battle junk drawer objects with other junk drawer objects, but to implement business logic in an organized set. Take a specific need and describe it, including variations, in a single Context to coordinate the Data and Interactions. The Context has real meaning and real value to your business, it's not just a place to use extend on your objects.

In Rails, your controllers should handle the user actions that trigger these use cases. You might have multiple ways to trigger a use case. For example in a typical view your user can interact with objects in your system but in admin view another user can do the same with perhaps an alternate scenario allowing him to override certain aspects of the scenario. It makes a lot of business sense to look at this use case and scenarios together, so why not put that code into one place? Why not create Context that explains all of this for us in executable code.

Put your use cases in a set of executable code and trigger it from wherever your interface requires it. Before you attempt this, begin first by writing your use cases. Use cases reveal the needs of the program and also show the value of the DCI Context in centralizing your business needs.

I'm writing about this and more in "Clean Ruby" a book about DCI in Ruby that is a collection of research and tips from my experience in working with large and small applications and making them easy to understand and maintain.

OOP, DCI and Ruby - what your system is vs. what your system does

If you've read my previous article on the tip of the iceberg with DCI then you might be curious to find out more about it. You read a very simple example that was only used to make a point. But for sure, you're left wondering a bit:

  • Why not make some other class to manage this if we want to separate functionality?
  • Is this at odds with the program's "connascence"
  • And another good question came up in the comments: what about performance?

All of these, and more, are good questions. But first you need to get your head around why you would use a pattern like DCI. What does the approach with Data, Context, and Interaction have to do with Object Oriented Programming?

Your first challenge

You need to unlearn what you know to be OOP.

Not quite all of it, but you need to stop and reconsider what it means to be "object oriented."

It's very likely that you've been building programs that are "class oriented" and not "object oriented." Take a moment and look at your latest project and consider if that's true.

Class Oriented Programming

You might call your program "class oriented" if your classes define both what an object is and what it does. If you need something else to happen to or with that object then what's your answer?

Do you add more methods to it's class or do you make a new class of thing to abstract the management of some task?

If you do either of those, it could be called class oriented.

Think about what this comment from Joe Armstrong might mean in Coders at Work: "The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."

Can that be applied to your objects?

Object Oriented Programming

When we program with OOP we care about objects, not only classes.

What DCI attempts to do is separate what the system is from what the system does. With this type of approach you'll get a truer mental model of your program. And your code concepts will be far closer to what you experience in the real world.

"But classes represent what things are! And different things behave in certain ways" you might say. This may, on the outset, seem to be true, but if you think about the things in the real world, they don't do anything unless they are playing some role.

Objects and Roles

The problem with relying upon classes and inheritance to define object behavior is that the behavior is fixed at compile time and your objects are limited in what actions they perform.

For example, you might have a Person class that is the basic model representation of a human being. That person is also a student, so you make a Student subclass. Eventually the student needs to get a job to pay for books and you need to make an Employee class. Should employees inherit from students? No, that's not right. Should the student inherit from employees? That's not right either.

Really, what you have is an object, a person, that needs to play many roles. With DCI, the approach is obvious: when the object needs to play a role, it is given that role.

Obvious Code

Yeah, but how often does this happen? Isn't your example contrived?

This type of inheritance problem may not happen often in your programs, but it does happen and you're likely to run into it at some point. And when it does happen what will you do?

I'll make another object to manage the work. Maybe the Person has many tasks and I can just make a TaskPerformer object to handle that.

While making another object to handle behavior may solve the problem with better encapsulation, your code is less representative of how the real world actually works. By making your code less like the real world, it makes it more difficult for you and others to reason about it's functions. And by introducing an abstract object, you've introduced something that doesn't make sense in the real world. Does a person have a task performer or does a person just perform a task?

The benefit in approaching objects and roles like this is that it makes your code more obvious. In the context of some event, an object is given a role and has methods defined to perform some action. By explicitly assigning roles to objects in a context, your code is instantly more decipherable.

Let's look at a simple example:

current_user.extend Admin
    current_user.grant_permission(other_user)
    current_user.extend Notifier
    current_user.send_thank_you_to(other_user)

In the example code, we see when an object gets a role, and performs some action. Looking at that code, one could assume that the modules used to extend the objects define the methods used.

Compare that code with this:

current_user.grant_permission(other_user)
    current_user.send_thank_you_to(other_user)

Are those methods defined on the class? Are they in another module that's included in the class? Perhaps. And yet you might need to break out grep to look around for def grant_permission in your project to find out exactly what that method does.

By defining these methods directly in an object's class, we're convoluting what the system is with what the system does. By separating the actions in to Roles, we're drawing a clean line between our representation of data (what it is) and the use cases that our system is designed to implement (what it does).

Separate Object from Role

With Ruby, we can easily just define new methods on an object with extend. This gives you the ability to easily break apart your concerns.

Here's something to try: the next time you need to implement a feature begin by writing some pseudo-code. Take the details of what needs to be done and add them as comments. Then gather your objects and assign to them some roles that make sense for what needs to be done.

# A user submits a form to request permission to access our system
    # If there is an available opening
    team.extend AvailabilityChecker
    if team.available_opening?
      applicant = User.find(params[:id])
      applicant.extend Applicant
      # and the user has completed the application, send it to processing queue
      if applicant.completed_application?
        applicant.prepare_for_acceptance
      else
        # If the user hasn't completed the application, ask them to complete it
        render 'edit', :notice => 'Oops! Please finish this.'
      end
    else
      # If there is no available opening, display a message
      redirect_to :index, :notice => "Bummer, dude! We're all out of space."
    end

The sample I gave is completely unreal and off the top of my head; don't read too much into it. But if you take a glance you'll see that it's pretty obvious where I intend these methods to be defined. It's likely that others on my team would find it obvious too.

Another benefit is that I didn't add any new methods to my user class. My code won't infect any other feature or test developed by others and by not adding more methods to the user class I don't add any overhead to understanding it.

Once I have that pseudo-code that describes the behavior, I can comment it out and start writing tests while I re-implement each tested piece.

Try this approach to see whether the experience is good or bad. (Note that this doesn't have to happen in your controller. You might implement this in a separate object, a Context which coordinates the knowledge of these objects and roles).

Does it make your code more obvious? Did it make testing any easier? What did others on your development team think when they saw it?

4 Simple Steps - Extending Ruby Objects - The Tip of the Iceberg with DCI

You've got a few Rails applications under your belt, perhaps several. But something is wrong. As you go, your development slows and your classes become bloated and harder to understand.

Keep your program simple

While you're doing your best to follow the concept of keeping your controllers skinny and your models fat, your models are getting really fat.

The answer is simple: cut the fat.

Your models don't need to have every method they will ever need defined in the class. The reality is that the objects that your application handles only need those methods when they need them and not at any other time. Read that again if you must, because it's true.

Step 1: Evaluate your code and look for a place to separate concerns

This is the point where you look at your code and try to realize what object needs what and when.

For example, if users of your system need to approve a friend request they only need to do it in the context of viewing that request. Your User class or @current_user object doesn't need this ability at any other time.

Step 2: Prepare your test suite

If you want to make your code simpler and easier to understand, write tests. You must do this first.

Even if you're only intending to change one small thing (just one tiny piece), write a test for that. You need a baseline.

Step 3: Create the Object Roles

Take your friend approval (or whatever it is) method or methods and put them in a module.

You might want to drop this into some namespace such as ObjectRole::FriendApprover or if you know your name won't clash with anything else, just go with FriendApprover.

Here's a sample of what this might look like:

module FriendApprover
      def approve(friend_request)
        friend_request.approved = true
        friend_request.save
        increment_friends
        notify_new_buddy(friend_request.user_id)
      end

      def increment_friends
        friend_count += 1
        save
      end

      def notify_new_buddy(buddy_id)
        BuddyMailer.notify_buddy(buddy_id, "We're officially friends!")
      end
    end

It doesn't really matter what my sample code is, you get the picture: take the methods from your User class that do the approval and put them in your FriendApprover module.

The unit tests you had for these methods can now be simplified and applied to the module. The test just needs to check that some object agrees to the contract that the methods expect.

Step 4: Extend your user

Extend your user. Thats little "u" user. Your class doesn't need this module, your object does.

Open up your controller where you usually call current_user.approve(friend_request) and change it to:

current_user.extend FriendApprover
    current_user.approve(friend_request)

That's it.

What you've just done

You've made your code more obvious.

It's only in this context that a user needs to perform this action and this change has limited the scope of those methods to a very concrete area.

  • Your User class is smaller making your cognitive strain easier
  • Your User unit test is smaller
  • You have a clear separation of concerns with your new Object Role module
  • You've inherently made these methods reusable

But what about...

Yes, there's more to it. Of course there's more you can do, but with this simple concept you can do a lot of cleanup of both your code, and your ability to reason about your code.

What is DCI?

For now, I'll leave the description of what DCI is to this article but I'll be writing more about the concepts in Data Context and Interaction.

How delete on a Hash works in Ruby... or how you thought it worked

Are you new to Ruby? Or were you once? Cool, me too.

When you first bump into Hash#delete you think you might be able to use it and just remove the items you don't want, but it doesn't work that way.

You think "I'll just do this:"

hashy = {'this' => 'that', 'something' => 'else', 'secret' => 'I love NKOTB'}
    hashy = hashy.delete('secret')

And bingo you've got your hash without that nasty secret. But what you actually found is that delete will remove that key from the hash and return the deleted value and not the altered hash.

Perhaps this is old news to you, but to new developers this is the moment where they say "Oh, right, it gives me the value that I don't want."

Well here's a quick idea to give you what you want:

class Hash
      def except(which)
        self.tap{ |h| h.delete(which) }
      end
    end

Now you can use the same code above but run:

pre>hashy = {'this' => 'that', 'something' => 'else', 'secret' => 'I love NKOTB'} hashy = hashy.except('secret')

That'll return your hash without the part you want. That could be simplified to this:

hashy = {'this' => 'that', 'something' => 'else', 'secret' => 'I love NKOTB'}
    hashy.except('secret')

because the delete will alter the hash. So you need to be aware that if you want to keep the original hash you'll need to:

hashy = {'this' => 'that', 'something' => 'else', 'secret' => 'I love NKOTB'}
    new_hash = hashy.dup.except('secret')

Enjoy!

Always check in schema.rb

Sometimes developers are unsure about Rails' schema.rb file and whether or not it should be checked in to source control. The answer is simple: yes.

As you are familiar, Rails encourages developers to alter the database state through migrations. One migration adds some table, and the following migrations add more, change something, or remove something. And as you well know, this is a great way to keep developers in sync with each other's changes to the database structure.

With each migration you add and subsequently run, your schema.rb file is altered to represent the final state of your database. Seemingly because this is automatically done for you, some developers think this file should be left out of your project; it should not.

Don't store it just because David Heinemeier Hansson said you should

First things first, this is a terrible reason to add schema.rb to your source control. Often, in an argument about something like this it's easy to look to an authority, find a relevant quote and say "See, he said so." Yes, there is a commit in Rails where he suggests you store schema.rb, but this was done to end an argument, it is not an argument itself.

Authorities are authorities because of their deep understanding of something, not because they command you to do things. But often people will allow authorities to command them to do things because they are authorities. David Heinemeier Hansson is an authority on Rails and his control of the project allowed him to make that commit and force the direction of Rails. If you agree with this commit, agree because of the reasoning, not because DHH said so.

Don't store generated files, except for schema.rb

As a general rule of thumb in compiled languages, you don't store generated files. The reason for this is not because an authority said so or because many consider it to be a good rule to follow, but because you want your code to generate the proper files for correct execution of the application.

If you add your generated files to your source control you may in the future find that you've altered your code in a way that prevents a particular file from being generated at all. But if that file exists regardless of the bug you introduced you're likely to find errors in the application's behavior. Tracking that down may be tough until you realize that you've checked-in your generated files.

Additionally, if you store generated file X in source control but change the code to instead generate file Y, you'll leave unused code in your project possibly giving other developers the misconception that it is important in some way. Worse yet, depending on your application the mere presence of file X could affect the execution of your application. I've heard things like this appropriately called "code turds." If it's not going to be used, it shouldn't be there.

Regardless of all of this, schema.rb doesn't affect the execution of your application so there is no danger in storing it in source control. Avoiding generated files in source control is a good rule to follow, but knowing when to break that rule is important too. Leave the code turds out and schema.rb in.

File churn in source control is not an issue with schema.rb

If you are concerned about the amount of churn (that is, frequent changes) you have with the development of your schema.rb file, then you probably are actively developing your database, or you have a problem elsewhere and need to get your team to work on a clearer picture of what your database should do.

Churn in schema.rb can actually be valuable, however. It's easy to overlook multiple migration files changing things in your database, but in reviewing code commits the amount of churn in an area of schema.rb can reveal problems with your development team.

Conflicts in schema.rb are valuable

If your team is making dueling commits over the purpose of a database field, your problem is not with resolving conflicts in schema.rb, it's with resolving conflicts between and among your developers about the structure of your database. Keeping schema.rb in source control will help to reveal this.

Before you commit any of your files to your master/production/whatever branch, you should

  1. run your tests
  2. pull down and merge any other changes
  3. re-run your migrations if any new ones were pulled down
  4. re-run your tests
  5. commit/push your changes (including schema.rb)

Following those steps ensures that your tests are run against the database that everyone else will have and ensures that the schema.rb file you commit is the latest and most up-to-date. Maybe you don't want to run your tests twice, that's fine, but be sure to run them after you pull down the latest code for the project and merge your changes.

Store it because schema.rb is a representation of the current state of the database

At any point in development, you can look at schema.rb to give you an accurate representation of your database structure. Other developers can checkout the project and run rake db:schema:load and almost instantly they are ready to develop (barring any sample data they need to load).

For a new team member, there is absolutely no need to change or rename anything in the database as may be done with migrations. Your ultimate goal to begin development is to have a database in a desired state. It doesn't matter a bit if a field name was changed from "login" to "username" or if your :text field was once a :string field in your first migration. For your database structure, the final state is all that matters, and schema.rb does this for you.

Application code mixed with migrations can cause problems

Sometimes you may have a need to alter your structure and do something like ProductType.reset_column_information in a migration and add some data. For now, I'll avoid the discussion on whether or not that's appropriate, but if you are doing this a problem may arise when at some point in time you remove the ProductType model, or rename it to Category. In that case, you'll need to go back and maintain your migrations... read that again you'll need to maintain your migrations. This is a pointless exercise: use schema.rb.

This is also an example of why you shouldn't mix database seeding and migrations.

Migrations are slow

Relying on migrations to get up to speed for development is slow and gets slower as your application's database changes and as the number of your migrations increases. Because schema.rb skips over changes and represents the final (and desired) state of your database, it's fast.

Your blank slate production database only needs the final state

A production database only needs the final state assuming, of course, that the database is a blank slate. Running all of the migrations in production to get where schema.rb would be is not necessary. schema.rb weeds out all of the changes for you and gets the job done quickly.

"But what about a database that already has a structure?" you may ask. Then all you need is the migrations that haven't been run; you'll never run rake db:schema:load on an existing production database.

Keep schema.rb with your code

schema.rb in your project's source control adds value for all developers. It loads the desired state quickly, it gives you a clear representation of your database structure, it reveals conflicts and unnecessary churn, it doesn't affect the execution of your application. Add schema.rb to your source control and add value for your team.

Ruby Metaprogramming is Awesome

If you've come to read about how wrong I am about metaprogramming, don't worry, I'm sure I'll follow-up with a post about how bad it is to do metaprogramming and how it causes you real, physical pain.

If, however, you've come to find out about how awesome metaprogramming is, then you can tell by the title of this article that you are in the right place! Now that's authoritative!

The best part about this article is that it is for you! That's right, newbie. I'm not going in-depth, I'm merely going to discuss how a dash of metaprogramming solved an annoying problem.

I do a lot of work with Radiant. And Radiant manages pages well, but there are plenty of extensions that allow you to do other things. You can, for example, add the ability to upload files and whatnot. Or you can add the ability to edit stylesheets and javascripts.

That's pretty cool. Radiant does a good job of managing pages in the pages table. But stylesheets and javascripts are not pages. Some of the samples that Radiant bundles have stylesheets as regular pages in the page tree and are tied to an almost blank layout that sets a particular content-type like text/css. Yuck. So Chris Parrish, the author of SNS, added text_assets to handle other types of content like stylesheets and javascripts.

One of his reasons for creating this extension is the weirdness of having a stylesheet in your page tree: "No more confused users wonder what those fancy pages are." Saaaweet! Thanks, Chris.

All is well until you find out that the SNS extension doesn't let you use your typical Radius tags within javascripts or stylesheets like:

#something { background: url('< r:assets:url title="my_image" />'); }

Nooooooo! Why, God, why!?!

Well, with SNS, you're dealing with a TextAsset and not a Page. But if you're familiar with Radiant, you know that page tags aren't only used on pages, they're used on snippets and layouts too. So what's the deal with that?

All of the radius tags that you use in Radiant are evaluated in the context of a single page. Pages, snippets, and layouts are all used in reference to rendering a Page. But SNS renders a TextAsset and as a result, it doesn't have any of the fancy tags added. Afterall, it's class TextAsset < ActiveRecord::Base and not class TextAsset < Page.

You read that right: text assets are not pages. Bummer, dude.

Well, what if you could include the same modules as are included in the Page model? Then you could use those tags in your stylesheets.

Fire up your console because you're about to see how to do it. In a rails console (for a Radiant instance), try this:

Page.included_modules

And you'll get back a bunch that don't matter for you. Let's simplify that:

>> Page.included_modules.select{|m| m.to_s =~ /Tags$/}
    => [TextileTags, SmartyPantsTags, MarkdownTags, StandardTags]

Awesome. All we need to do is include all of those modules into TextAsset and we're done! Almost.

Since we're dealing with the SNS extension, you'll also see that it includes Sns::PageTags which adds tags to output stylesheets and javascripts. Those, we don't need. So we can filter them out and include them into TextAsset:

TextAsset.class_eval {
      Page.included_modules.select{|m| m.to_s =~ /Tags$/}.reject{|m| m == Sns::PageTags }.each do |mod|
        include mod
      end
    }

Bingo! Now we're in business. Except for the fact that it doesn't work.

So we need to update the context in which these tags are evaluated. Since they are all written expecting to be included in a Page model, the global variables for the tags need to have knowledge of a page.

TextAssetContext.class_eval {
      def initialize(text_asset)
        super()
        globals.page = text_asset # This is the important line that adds the hook for all existing tags for pages.
        globals.text_asset = text_asset
        text_asset.tags.each do |name|
          define_tag(name) { |tag_binding| text_asset.render_tag(name, tag_binding) }
        end
      end
    }

There you have it. All it took was some class_eval and some looping over included_modules.

page tags in stylesheets And now you'll have happy users. Because even though Chris solved the problem of weird stylesheet pages in the page tree, the solution introduced a problem where editors of the site expect the radius tags to simply work everywhere. Now they do.

The above code assumes that the only valuable tags are those whose modules have "Tags" at the end of their names. That's a reasonable expectation, but we can go even further by inspecting the included modules of the included modules to see if Radiant::Taggable is there:

TextAsset.class_eval {
      Page.included_modules.reject{|m| m == Sns::PageTags }.each do |mod|
        if mod.included_modules.any? {|inc| inc == Radiant::Taggable }
          include mod
        end
      end
    }

So go ahead and install the page attachments, or paperclipped, or whatever extension with sns and just do script/extension install sns_page_hook, or better yet: gem install radiant-sns_page_hook-extension. Please let me know if you find any problems with it.

Radiant 0.9 Official Release

Finally, after a long, long wait: 0.9 is out.

It's my first non prerelease gem to push out for Radiant but I'm proud of all the work that I and many, many others did to make it happen. John Long put the UI updates together with the help of a good group. Keith Bingman managed all that went into internationalization and the many contributors that made it happen. William Ross added features such as pagination in the standard Radius tags, and pagination in the admin screens. Josh French gave us the ability to load extensions from gems. John Muhl, our newest core team member increased the general quality in testing for bugs and improving the overall quality of the application.

There are many contributors, I'm just listing some from the top of my head. Thank you to everyone of the contributors, be you bug reporters, committers, or just users who discuss your needs on the mailing list.

While this release is an exciting improvement, I'm even more excited about the future of the project. More to come...

Rack Cache on Heroku with Memcached

The convenience of deploying application on Heroku is attractive especially with their add-ons and the free options that they provide, in particular Memcache.

If you're working with an application which needs to manage it's cache with Rack::Cache, you'll want to have fast responses for your metastore. The meta information about your content is probably the most important part of your cache since it's checked by many clients for the status of the content: is it fresh or stale? See more about How Web Caches Work.

Typically you might setup Rack::Cache like this:

config.middleware.use Rack::Cache, :metastore => 'file:tmp/cache/meta', :entitystore => 'file:tmp/cache/entity'

5MB of Memcache is a decent place to start for free and it's integrated into your application without any effort on your part. So on Heroku you can use Memcache as your metastore like this:

$cache = Memcache.new
    config.middleware.use Rack::Cache, :metastore => $cache, :entitystore => 'file:tmp/cache/entity'

That's simple enough, and it's just as easy if you're deploying Radiant:

$cache = Memcache.new
    config.middleware.use Radiant::Cache, :metastore => $cache

If you want to look at an example of a simple app that does this, there's an easy to understand sample application on github. Enjoy your speedy metastore.

Radiant Page#find_by_url

On a recent project a client asked about overriding Page#find_by_url and when that actually occurs. I think the answer should be explained for everyone working with it.

20 second summary

This is an in-depth look at the method that gathers pages within Radiant. In short, if you want to do special page finding, create a subclass of Page and write your own find_by_url method to adjust the way Radiant behaves. Every page will respond to this method and return appropriate pages according to the requested url. In the admin interface, you can select your special page type to make that page behave as you have specified.

Simple finding

find_by_url is defined both as a class method and an instance method. Let's look at the class method Page.find_by_url from the Page model:

class << self
      def find_by_url(url, live = true)
        root = find_by_parent_id(nil)
        raise MissingRootPageError unless root
        root.find_by_url(url, live)
      end
      # ...
    end

First, it looks for the root page, which is considered the page with no parent_id. If no root page is found it raises a MissingRootPageError exception; otherwise, it calls the instance method find_by_url on the root page.

This class method takes 2 arguments: the url (really the path matched in the routes from request) to be found, and a live flag which defaults to true (more about that later).

Finding the first page

The find_by_url instance method is a bit more complex. Let's take a look:

def find_by_url(url, live = true, clean = true)
      return nil if virtual?
      url = clean_url(url) if clean
      my_url = self.url
      if (my_url == url) && (not live or published?)
        self
      elsif (url =~ /^\#{Regexp.quote(my_url)}([^\\/]*)/)
        slug_child = children.find_by_slug($1)
        if slug_child
          found = slug_child.find_by_url(url, live, clean)
          return found if found
        end
        children.each do |child|
          found = child.find_by_url(url, live, clean)
          return found if found
        end
        file_not_found_types = ([FileNotFoundPage] + FileNotFoundPage.descendants)
        file_not_found_names = file_not_found_types.collect { |x| x.name }
        condition = (['class_name = ?'] * file_not_found_names.length).join(' or ')
        condition = \"status_id = \#{Status[:published].id} and (\#{condition})\" if live
        children.find(:first, :conditions => [condition] + file_not_found_names)
      end
    end

Wow. There's a lot going on there and there's room for some refactoring, but for now let's just walk through it.

First, nil will be returned if the page is virtual?. A page, by default, is not virtual. This is stored in the database in a boolean field, but you may override this in any subclass of Page that you create. For now, let's assume that your page isn't and won't be virtual and we'll get back to what it means.

Next, we clean the url if the clean flag is set to true (which it is by default). clean_url simply ensures that the url being checked is properly formatted and that any doubling of slashes is fixed. So this right//here//// becomes this /right/here/.

The next step shows us why we clean the url. A local variable is setup to compare against the page's url.

my_url = self.url
    if (my_url == url) #...

What is a page's url? It's calculated by the page's slug and the slugs of it's ancestors. In short, if your current page's slug is 'here' and it's parent page is 'right', and that page's parent is the home page (with a slug of '/') then your current page's url is '/right/here/'.

So we check to see that to see if it is the same as the url in the request. But also, in this comparison, we check to see if the live flag is set and is false or if the page is published?.

This live flag is a bit strange in appearance:

my_url = self.url
    if (my_url == url) && (not live or published?)

By default, this not live returns false (since live is true by default and we reverse it with not) so it moves on to published?. You might set live to false in other situations, but for now we'll just go with this.

A page is published? if it's status (as stored in the database) is the 'Published' Status.

So if the incoming url matches the current page's url (which at the first pass is the root or home page), then we return with the current page:

my_url = self.url
    if (my_url == url) && (not live or published?)
      self

Finding deeper pages

If it isn't true that the incoming url and the current page's url are equal, then we move on to the next step:

my_url = self.url
    if (my_url == url) && (not live or published?)
      self
    elsif (url =~ /^#{Regexp.quote(my_url)}([^\/]*)/)

Here it matches the incoming url against a Regexp of the current page's url. When it starts, we're matching the root page which has a url of '/'. If that's the incoming url, it would have been caught in the original if block, but we ended up at the elsif. The Regexp that's used matches the next slug in the incoming url. So if the incoming url is '/right/here/' then it will match the slug 'right'.

From that match, we find the current page's children by their slug (remembering that the current page is the root, with a slug of '/'):

elsif (url =~ /^#{Regexp.quote(my_url)}([^\/]*)/)
      slug_child = children.find_by_slug($1)

If it finds that 'slug_child', then we call find_by_url on that page to loop down the tree to find the final page that we want (which would be the page that responds to the url '/right/here' or in this simple case, the page with a slug of 'here'). If it finds the page, then it returns the found page:

slug_child = children.find_by_slug($1)
      if slug_child
        found = slug_child.find_by_url(url, live, clean)
        return found if found
      end

In that if slug_child block, the slug_child.find_by_url acts as a loop. Because every page responds to this method and will do exactly what is happening here for the root page, each page will search it's children for a slug matching the slug from the incoming url and any found page will likewise call find_by_url to search it's children as well.

There is some room here for some optimization in the way we do a lookup for a page, but for now it works and we can get to the refactoring another time.

When no slug is found: customizing the finder

If the slug_child is not found (and no child matches that slug) then this if slug_child block is never hit and we move to the next step. This is where the magic happens for subclasses of Page:

children.each do |child|
        found = child.find_by_url(url, live, clean)
        return found if found
      end

It asks each child of the current page if it responds to find_by_url and returns any found page.

So even if none of the pages are found by the slug, we still ask the children if they respond to find_by_url. Why would we do this?

The answer lies in one of the included extensions: Archive.

The ArchivePage is a subclass of page which provides it's own find_by_url method. The ArchivePage#find_by_url will check the incoming url for it's details and if it meets certain requirements (namely that there is a standard date format in the url such as 'articles/2010/06/22') then it will find the appropriate page type such as ArchiveDayIndexPage, ArchiveMonthIndexPage or ArchiveYearIndexPage and return the proper page. If none of those are found it just calls super and calls the original Page#find_by_url.

This can act as your router for your custom page types. If you want to return a particular page type, such as a ProductsPage and your url is '/products/1234' then you can create a ProductPage which has it's own find_by_url method and would find your ProductDetailsPage to display a standard view of all of your products based upon the slug '1234' which I'd assume would be a product id, but could be anything you want.

Handling 404

Lastly, if none of this finds any pages to return, Radiant has a FileNotFoundPage page which allows you to easily create your own 404 error message for content that isn't found. You can subclass a FileNotFoundPage page to provide your own behavior there too. But when searching for a match to an incoming url, Radiant will find deeply nested 404 pages. So you can create a FileNotFoundPage as a child of your root page, but you can also create a FileNotFoundPage as a child of your ProductsPage to return an appropriate message to someone looking for '/products/not-a-valid-url'.

Here's the code for that last step:

file_not_found_types = ([FileNotFoundPage] + FileNotFoundPage.descendants)
      file_not_found_names = file_not_found_types.collect { |x| x.name }
      condition = (['class_name = ?'] * file_not_found_names.length).join(' or ')
      condition = "status_id = #{Status[:published].id} and (#{condition})" if live
      children.find(:first, :conditions => [condition] + file_not_found_names)

The live flag comes into play here again and optionally allows you to find pages that are not published. By default live is true, so in this instance we only check for a FileNotFoundPage that is published.

Radiant has a 'development' mode which would find unpublished pages, but that's a subject for another discussion.

I hope this gives you a good understanding of how Radiant finds its content, and how you can easily bend it to behave differently by creating a subclass of Page and writing your own find_by_url method. If I've left anything out or if you want me to cover some other aspect, let me know in the comments.

Combining show_for and stonewall

I'd been doing some thinking about simplifying the display of records in Rails applications and fortunately came across show_for.

show_for is a formtastic-like approach to displaying details about database records. It helps you DRY up your views and can even reflect on associations with code like this:

<% show_for @user do |u| %>
  <%= u.attribute :name %>
  <%= u.attribute :nickname, :in => :profile %>
  <%= u.attribute :confirmed? %>
  <%= u.attribute :created_at, :format => :short %>
  <%= u.attribute :last_sign_in_at, :if_blank => "User did not access yet",
                  :wrapper_html => { :id => "sign_in_timestamp" } %>

  <% u.attribute :photo do %>
    <%= image_tag(@user.photo_url) %>
  <% end %>

  <%= u.association :company %>
  <%= u.association :tags, :to_sentence => true %>
<% end %>

But since I'm working on an application which uses stonewall (which allows you to limit the display of a record's details), I needed the 2 of them to work together.

stonewall allows you to guard the display of your data from your models:

stonewall do |s|
  s.varies_on :aasm_state

  s.guard_attribute :secret_cultivation_details

  # ... role details here
end

It provides a allowed? method which you can use to ask an object if the current user is allowed to see the content.

So I quickly put together show_for_stonewall which will limit the display of certain fields if stonewall prevents it. It was as simple as using alias_method_chain to check that an attribute is not allowed

!allowed?(@object, current_user, attribute_name)

You can edit your show_for translation yaml and add a redacted key for the content to display if a field is not allowed for the current user.

Adventures in Javascript

I wrote a simple Javascript library for myself in 2006 called simpleDOM.

At the time, there was a problem with using innerHTML in Internet Explorer to write content to a page and then select it when traversing the DOM or submit a form with the added content. Not only that, but it's expensive to process and manipulate DOM objects in the browser while they are displayed so this library gave me an easy way to create document fragments and manipulate those to then be injected in the right place.

Over time, I got into working with other libraries and problems like this were solved for me, so I never did much more with it.

I've still got it working in one production site but haven't looked at it in a long time. I thought I'd put it out there on github for posterity.

Enabler: control Radiant sites

I've put together an extension which will allow you to turn on and off your instances of Radiant.

Enabler will allow you to post to your sites to disable and enable it's ability to serve content. You might use this extension if you host sites for your clients and they pay to you a monthly fee for service. If your customer has refused payment or if their payment bounces you can post to the_website.com/admin/disable/your-api-key and the cache will be cleared and the site will serve a simple message that the site is down.

You can change the message by adding a message parameter to your disable post. Just post to the_website.com/admin/disable/your-api-key?message=Please%20pay%20your%20bills

This will allow your customers to continue to login to the admin area but they won't be serving up any public content until their bill is paid and you post back to re-enable the site.

It's built for Radiant 0.9 and you can just gem install radiant-enabler-extension and load it up in your environment.

This isn't an extension you'd use manually and you'd probably want to tie it to a billing service such as Spreedly so that a site is automatically turned off when there is no payment.

To prevent delicious malicious hackers from scanning sites for this extension it will respond with a typical Radiant response for the URL rather than a 403 Forbidden error code as you might expect. If someone posts to your site with an invalid key, Radiant will simply respond with the usual 404 from your FileNotFound page.

If you think it could use a feature to turn off admin access too, just code and send me some pull requests.