2

My team has been reading existing ruby code to build our understanding. We commonly find things we don't quite understand, even with research. Please comment on the following questions.

Question 1

For the following code, why is class << self defined right under the module name? Does that imply defining a class with the module name?

module GravatarImageTag

  class << self
    attr_accessor :configuration
  end

Question 2

Why does the author define class << self and go on to define methods with self.? Our understanding is thay you can define self. methods in a block that starts with class << self rather than repeat self. for each method.

module GravatarImageTag

  class << self
    attr_accessor :configuration
  end

  def self.configuration
    @configuration ||= Configuration.new
  end

  def self.configure
    yield(configuration)
  end

Question 3

Why does the author use the class name rather than self in the method self.include(base)? Furthermore, with this file's structure, what is class is self.include(base) a member of? This relates to question 1.

module GravatarImageTag

  class << self
    attr_accessor :configuration
  end

  def self.configuration
    @configuration ||= Configuration.new
  end

  def self.configure
    yield(configuration)
  end

  class Configuration
     attr_accessor :default_image, :filetype, :include_size_attributes,
       :rating, :size, :secure

     def initialize
        @include_size_attributes = true
     end
  end

  def self.included(base)
    GravatarImageTag.configure { |c| nil }
    base.extend ClassMethods
    base.send :include, InstanceMethods
  end   

Thanks.

Joe Essey
  • 3,457
  • 8
  • 40
  • 69
  • @sawa I was going to comment something similar, but then realized that these questions do seem closely tied to each other and may not be very easy to separate. Idk though... – Ajedi32 Jun 13 '14 at 13:40
  • 1
    @Ajedi32 I understand what you mean, but overall, it is too long. It needs to be either more concise, or separated. – sawa Jun 13 '14 at 13:41
  • Related: [class << self idiom in Ruby](http://stackoverflow.com/questions/2505067/class-self-idiom-in-ruby), [Module#included](http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-included) – Ajedi32 Jun 13 '14 at 13:44

1 Answers1

0

Little Bit Explanation:

class << self is more than just a way of declaring class methods (though it can be used that way). Probably you've seen some usage like:

class Foo
  class << self
    def a
      print "I could also have been defined as def Foo.a."
    end
  end
end

This works, and is equivalent to def Foo.a, but the way it works is a little subtle. The secret is that self, in that context, refers to the object Foo, whose class is a unique, anonymous subclass of Class. This subclass is called Foo's eigenclass. So def a creates a new method called a in Foo's eigenclass, accessible by the normal method call syntax: Foo.a.

Now let's look at a different example:

str = "abc"
other_str = "def"

class << str
  def frob
    return self + "d"
  end
end

print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str

This example is the same as the last one, though it may be hard to tell at first. frob is defined, not on the String class, but on the eigenclass of str, a unique anonymous subclass of String. So str has a frob method, but instances of String in general do not. We could also have overridden methods of String (very useful in certain tricky testing scenarios).

via David Seiler

Gagan Gami
  • 10,121
  • 1
  • 29
  • 55