On Dec 3, 2011, at 3:44 PM, Chuck Remes wrote:

> 
> I should have waited a few more minutes. After typing this up, I was hit by inspiration. Here is my solution.
> 
>    def self.create_combination(mod, fields)
>      processed = []
>      string = "def each_combination(&blk)\n"
> 
>      fields.each_with_index do |field_name, index|
>        string << ("  " * (index + 1)) + "each_#{field_name} do |#{field_name}|\n"
>        processed << field_name
>      end
> 
>      string << ("  " * (processed.size + 1)) + "yield(#{processed.join(', ')})\n"
>      processed.size.downto(1) { |i| string << ("  " * i) + "end\n" }
>      puts string
>    end

And once again I should have waited a few minutes or at least long enough to run my test. Here's a bug fix for the missing "end" to close the method definition (it's the call to #downto).

    def self.create_combination(mod, fields)
      processed = []
      string = "def each_combination(&blk)\n"

      fields.each_with_index do |field_name, index|
        string << ("  " * (index + 1)) + "each_#{field_name} do |#{field_name}|\n"
        processed << field_name
      end

      string << ("  " * (processed.size + 1)) + "yield(#{processed.join(', ')})\n"
      processed.size.downto(0) { |i| string << ("  " * i) + "end\n" }
      puts string

      mod.class_eval(string)
    end