views:

181

answers:

3

Hi All,

I have installed the acts_as_versioned plugin from github.com in my rails application, and there was a block of code that I don't fully understand, I was hoping someone could clear this up for me

class_eval <<-CLASS_METHODS
  def a_bunch_of_stuff
   ....
  end
CLASS_METHODS

I get that the methods inside the block (or whatever it is) gets defined as instance methods inside the class, but I can't find CLASS_METHODS defined as a constant anywhere in the plugin, and I'm also not sure what <<- after class_eval means. the plugin is located here, and the code in question starts on line 199 of lib/acts_as_versioned.rb. If someone would give me the lowdown here, I would be much-obliged.

thx

-C

+5  A: 

This is a "here document", which is a way of quoting large multiline strings inline. From Programming Ruby:

Strings can continue across multiple input lines, in which case they will contain newline characters. It is also possible to use here documents to express long string literals. Whenever Ruby parses the sequence <<identifier or <<quoted string, it replaces it with a string literal built from successive logical input lines. It stops building the string when it finds a line that starts with the identifier or the quoted string. You can put a minus sign immediately after the << characters, in which case the terminator can be indented from the left margin. If a quoted string was used to specify the terminator, its quoting rules will be applied to the here document; otherwise, double-quoting rules apply.

This will cause class_eval to treat the stuff between CLASS_METHODS as a string and execute it in the appropriate context. The use of the name CLASS_METHODS is arbitrary, it could just as easily have been called anything else.

Greg Hewgill
+4  A: 

It's a heredoc. http://en.wikipedia.org/wiki/Heredoc#Ruby

The matched CLASS_METHODS tokens are essentially starting and ending quotes. If you use <<- instead of <<, the ending token can be indented with whitespace.

You can use multiple heredocs at once in Ruby (I made my heredocs the same as the argument names, but that's just for aesthetic - it makes no difference):

def define_with_description description, code
  puts "defining a method to #{description}"
  class_eval code
end

define_with_description <<-DESCRIPTION, <<-CODE
  set up us the bomb
DESCRIPTION
  Bomb.new.set_up(us)
CODE
ben_h
A: 

These are equivalent:

class SomeClass
  class_eval <<-CLASS_METHODS
    def first_method
    end
    def second_method
    end
  CLASS_METHODS
end

class SomeClass
  def self.first_method
  end
  def self.second_method
  end
end
Michael Gee