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

···

--
Posted via http://www.ruby-forum.com/.

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

On Nov 22, 12:58 pm, Greg Willits <li...@gregwillits.ws> wrote:

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
--
Posted viahttp://www.ruby-forum.com/.

Greg Willits 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!"

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

···

--
Posted via http://www.ruby-forum.com/\.

Gavin Kistner wrote:

Greg Willits 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

···

--
Posted via http://www.ruby-forum.com/\.

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

···

--
Posted via http://www.ruby-forum.com/.

Greg Willits wrote:

Gavin Kistner wrote:

Greg Willits 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

···

--
Posted via http://www.ruby-forum.com/\.