Ruby adapter template: access to your instances

I am studying adapter implementation in ruby. I want to access the instance variable in the adapter module definition. Take a look at the following code:

module Adapter
  module Dog
    def self.speak
      # I want to access the #name instance variable from my Animal instance
      puts "#{name} says: woof!"
    end
  end

  module Cat
    def self.speak
      # I want to access the #name instance variable from my Animal instance
      puts "#{name} says: meow!"
    end
  end
end

class Animal
  attr_accessor :name

  def initialize(name)
    @name = name
  end

  def speak
    self.adapter.speak
  end

  def adapter
    return @adapter if @adapter
    self.adapter = :dog
    @adapter
  end

  def adapter=(adapter)
    @adapter = Adapter.const_get(adapter.to_s.capitalize)
  end
end

To test this, I did the following:

animal = Animal.new("catdog")
animal.adapter = :cat
animal.speak

I want it to return the following:

catdog says: meow!

Instead, he says:

Adapter::Cat says: meow!

Any tips on how I can access the instance method Animal#namefrom the adapter module? I think the problem is that my adapter methods are class methods.

Thank!

+2
source share
2 answers

, , , , , .

module Adapter
  module Dog
    def speak
      puts "#{name} says: woof!"
    end
  end

  module Cat
    def speak
      puts "#{name} says: meow!"
    end
  end

  def extend mod
    @ancestors ||= {}
    return if @ancestors[mod]
    mod_clone = mod.clone
    @ancestors[mod] = mod_clone
    super mod_clone
  end

  def remove mod
    mod_clone = @ancestors[mod]
    mod_clone.instance_methods.each {|m| mod_clone.module_eval {remove_method m } }
    @ancestors[mod] = nil
  end
end

class Animal
  include Adapter
  attr_accessor :name, :adapter

  def initialize(name)
    @name = name
    @adapter = Adapter::Dog
    extend Adapter::Dog
  end

  def adapter=(adapter)
    remove @adapter
    extend Adapter::const_get(adapter.capitalize)
    @adapter = Adapter.const_get(adapter.capitalize)
  end
end

animal = Animal.new("catdog")
animal.speak # catdog says: woof!
animal.adapter = :cat
animal.speak # catdog says: meow!
animal.adapter = :dog
animal.speak # catdog says: woof!
+2

, name module - name, . Animal Cat , . , Module#name, Adapter::Cat .

, . module ( self, include ) , speak.

:

module Adapter
  module Dog
    def self.speak(name)
      puts "#{name} says: woof!"
    end
  end
end

class Animal
  attr_accessor :name
  attr_reader :adapter

  def initialize(name)
    @name = name

    self.adapter = :dog
  end

  def speak
    self.adapter.speak(@name)
  end

  def adapter=(adapter)
    @adapter = Adapter.const_get(adapter.to_s.capitalize)
  end
end

, , . Ruby-esque:

module Adapter
  module Dog
    def speak
      puts "#{name} says: woof!"
    end
  end
end

class Animal
  attr_accessor :name
  attr_reader :adapter

  def initialize(name)
    @name = name

    self.adapter = :dog
  end

  def adapter=(adapter)
    @adapter = Adapter.const_get(adapter.to_s.capitalize)

    extend(@adapter)
  end
end
+1

Source: https://habr.com/ru/post/1667828/


All Articles