1

How can I set some instance variables when extending a instance in the same way it can be done when creating it, with initialize.

In this example the variable set when extending is "lost":

module Mod
  def self.extended(base)
    @from_module = "Hello from Mod"
    puts "Setting variable to: #{@from_module}"
  end

  def hello_from_module
    return @from_module
  end
end

class Klass
  def initialize
    @from_class = "Hello from Klass"
  end

  def hello_from_class
    return @from_class
  end
end

klass = Klass.new       #=> #<Klass:0x00000000ed8618 @from_class="Hello from Klass">
klass.extend(Mod)       #=> #<Klass:0x00000000ed8618 @from_class="Hello from Klass">
"Setting variable to: Hello from Mod"

klass.hello_from_class  #=> "Hello from Klass"
klass.hello_from_module #=> nil (warning: instance variable @from_module not initialized)
2
  • 1
    The variable isn't lost. Instance variables belong to objects (instances), that's why they are called instance variables. What is the instance that your are setting the variable on? Well, the method is a singleton method of Mod, so self is Mod and the instance variable is an instance variable of Mod. Commented Oct 23, 2016 at 1:35
  • It's worth noting that return is implicit in Ruby, the last thing left on the stack is the return value by default, so it can usually be omitted if the last thing in the method is what you want as a return value. Commented Oct 23, 2016 at 4:39

1 Answer 1

2

There are a number of ways to do what you describe.

The most common one would be to use instance_variable_get and instance_variable_set:

module ModA
  def self.extended(base)
    base.instance_variable_set(:@from_module, "Hello from Mod A")
    puts "Setting variable to: #{base.instance_variable_get(:@from_module)}"
  end

  def hello_from_module
    return @from_module
  end
end

Another common technique is to use any of the eval or exec methods. In this case instance_exec:

module ModB
  def self.extended(base)
    base.instance_exec { @from_module = "Hello from Mod B" }
    puts "Setting variable to: #{base.instance_exec { @from_module }}"
  end

  def hello_from_module
    return @from_module
  end
end
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.