Class Methods from Modules

Can’t see the tree for the forest.

Playing with how to integrate modules, classes, subclasses, and create
instance methods and class methods from modules.

In this play code below, I want to use initialize_colors in either the
class Shape or Square as a class method.

At this point I’m sure I’m missing a very simple syntax rule explained
very clearly in the books, but the code as is complains about
initialize_colors as being undefined, and I’m just not recognizing what
I am missing.

module Color

def initialize_colors
@fill_color = ‘ffffff’
@border_color = ‘000000’
end

def set_fill_rgb(color)
if color == ‘white’
@fill_color = ‘ffffff’
elsif color == ‘red’
@fill_color = ‘ff0000’
elsif color == ‘blue’
@fill_color = ‘0000ff’
elsif color == ‘black’
@fill_color = ‘000000’
end
end
end

class Shape

include Color

attr_reader :fill_color, :border_color

def initialize
@fill_color = String.new
@border_color = String.new
end
end

class Square < Shape

initialize_colors

end

sq = Square.new
puts sq.fill_color
sq.set_fill_rgb(‘red’)
puts sq.fill_color

Hi Greg,

Well the methods you can call as a class is being defined are
class methods. initialize_colors is an instance method, as it
should be since it’s setting instance variables.

It seems to me that you want to call initialize_colors not as the
class is being defined but as instances are being created. And
therefore the call to initialize_colors should be inside Square’s
initialize method.

Eric

====

Are you interested in on-site Ruby training that’s been highly
reviewed by former students? http://LearnRuby.com

Eric I. wrote:

Hi Greg,

Well the methods you can call as a class is being defined are
class methods. initialize_colors is an instance method, as it
should be since it’s setting instance variables.

It seems to me that you want to call initialize_colors not as the
class is being defined but as instances are being created. And
therefore the call to initialize_colors should be inside Square’s
initialize method.

The exercise is to figure how to make initialize_colors work as a class
method – so if the instance vars are misleading, then it’s those I
would change.

I am just experiementing to understand with working examples how various
syntax and behavior are related in Ruby to acheive various levels of
functionality at the class, instance, and module realms.

Another way to look at this is that I’m trying to understand how some
things in Rails work by replicating them on a micro scale – in this
case a good example might be how the validates_ methods all work.
They’re called as class methods from within a subclass and I would
expect they’re implemented via modules. I’ve traced the source, but
there’s too much noise for me at this stage of my Ruby experience.

– gw

I found class << self, but still here’s an even simpler example that
doesn’t work as I thought it would:

module Color
def set_fill(color)
puts “testing”
@@fill_color = color
end
end

class Shape

@@fill_color = ‘black’

class << self
include Color
end

def self.fill_color
@@fill_color
end

end

Shape.new
puts Shape.fill_color

Shape.set_fill(‘red’)
puts Shape.fill_color

I get:

black
testing
black

–gw

Greg W. wrote:

In this play code below, I want to use initialize_colors in either the
class Shape or Square as a class method.

Including a module in a class causes instance methods of the module to
be in the lookup path for instances of the class. Extending a class
using a module causes instance methods of the module to be in the
lookup path for the class itself.

(See http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png)

A common idiom to be able to cause a class to get both class and
instance methods when including a single module follows:

module Color
module ClassMethods
def initialize_colors
p “woot!”
end
end

def giggle
puts “tee hee!”
end

def self.included(receiver)
receiver.extend ClassMethods
end
end

class Shape
include Color
initialize_colors
#=> “woot!”
end

Shape.new.giggle
#=> “tee hee!”

Gavin K. wrote:

Greg W. wrote:

In this play code below, I want to use initialize_colors in either the
class Shape or Square as a class method.

Including a module in a class causes instance methods of the module to
be in the lookup path for instances of the class. Extending a class
using a module causes instance methods of the module to be in the
lookup path for the class itself.

(See http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png)

A common idiom to be able to cause a class to get both class and
instance methods when including a single module follows:

Cool, thanks. But…

In this code the fill_color is still never set to black. It seems to me
that Module code even if added as class methods cannot access class
variables??

– gw

module Color
module ClassMethods
def initialize_colors
@@fill_color = ‘black’
p “woot!”
end
end

def self.included(receiver)
receiver.extend ClassMethods
end
end

class Shape
include Color
@@fill_color = ‘white’
initialize_colors

def self.fill_color
@@fill_color
end
end

Shape.new
p Shape.fill_color

Greg W. wrote:

Gavin K. wrote:

Greg W. wrote:

In this play code below, I want to use initialize_colors in either the
class Shape or Square as a class method.

Including a module in a class causes instance methods of the module to
be in the lookup path for instances of the class. Extending a class
using a module causes instance methods of the module to be in the
lookup path for the class itself.

(See http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png)

A common idiom to be able to cause a class to get both class and
instance methods when including a single module follows:

Cool, thanks. But…

In this code the fill_color is still never set to black. It seems to me
that Module code even if added as class methods cannot access class
variables?

OK, nevermind – I get it now.

even though they have the same name they are actually two independent
variables in the two separate “name spaces/realms” of the model & class
containers.

I thought the “inclusion” would fuse the two spaces into one.

– gw