The magical “self” when doing Mixin in Ruby

Here is a sample code snippet, which will show my problem. I put this file in the script directory of a Rails project to run.

$:.unshift(File.dirname(__FILE__) + "/../vendor/rails/activesupport/lib")
require 'active_support'

class App
end

module M
  def self.included(base)
    base.class_eval do
      class_inheritable_accessor :h
    end
    base.extend ClassMethods
  end
  module ClassMethods
    def not_work
      h = 1
    end
    def work
      self.h = 2
    end
  end
end
App.send(:include, M)

puts App.h
App.not_work
puts App.h
App.work
puts App.h

You could see that the “self” keyword made a difference when calling the reader method of a class_inheritable_reader. This looks really weird until I checked the implementation of class_inheritable_reader.

 def class_inheritable_reader(*syms)
    syms.each do |sym|
      next if sym.is_a?(Hash)
      class_eval <<-EOS
        def self.#{sym}
          read_inheritable_attribute(:#{sym})
        end

        def #{sym}
          self.class.#{sym}
        end
      EOS
    end
  end

2 thoughts on “The magical “self” when doing Mixin in Ruby”

Leave a Reply