Suppose I have two modules:
module Test1
  attr_accessor :a, :b
  @a = 0.0
  @b = 0.0
end
module Test2
  attr_accessor :c, :d
  @c = 0.0
  @d = 0.0
end
Now, I want to conditionally mix these modules into a class. This is what I've tried:
require './Test1.rb'
require './Test2.rb'
class MyClass
  def initialize(mode)
    if mode == 0
      (class << self; include Test1; end)
    elsif mode == 1
      (class << self; include Test2; end)
    else
      class << self
        include Test1
        include Test2
      end
    end
  end
end
This is the behavior I am seeing:
obj = MyClass.new(0)
obj.a  #=> nil
Also @a is nil in instance methods within the class. I feel that I am not understanding something important here. I would like to understand why what I'm doing isn't working and also what the correct way to achieve my desired functionality is.
You have this behaviour because these instance variables you set in modules belong to modules themselves instead of belonging to MyClass instances. Consider this code:
Test1.instance_variable_get(:@a)
# => 0.0
To solve this issue, you could use extend instead of include:
module Test1
  attr_accessor :a, :b
  def self.extended(object)
    object.a, object.b = 0.0, 0.0
  end
end
module Test2
  attr_accessor :c, :d
  def self.extended(object)
    object.c, object.d = 0.0, 0.0
  end
end
And in your class:
require './Test1.rb'
require './Test2.rb'
class MyClass
  def initialize(mode)
    if mode == 0
      extend Test1
    elsif mode == 1
      extend Test2
    else
      extend Test1
      extend Test2
    end
  end
end
                        I thought of a way to work around this problem, so I thought I'd share it. I'd still like to see if anyone knows of a better way to achieve what I was trying to.
Module Test1
  attr_accessor :a, :b
  def init1
    @a = 0.0
    @b = 0.0
  end
end
class MyClass
  def initialize
    if mode == 0
      (class << self; include Test1; end)
      init1
    elsif mode == 1
      ...
  end
end
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With