简体   繁体   中英

Ruby: How to set instance variables from a class method?

I'm not sure that's the right title for this question, but I don't know how else to ask it. I have classes that need to be registered globally so they can be called later. I have most of it working except for a very important part. When the child inherits from the parent class, it registers a new instance, but when the on_message class method is called, I can't figure out how to set the instance variables that I need.

class MyExtension < ExtensionBase

  on_message '/join (.+)' do |username|
    # this will be a callback function used later
  end

end

class ExtensionBase

  def self.inherited(child)
    MainAppModule.registered_extensions << child.new
  end

  def self.on_message(string, &block)
    # these need to be set on child instance
    @regex = Regexp.new(string)
    @on_message_callback = block
  end

  def exec(message)
    args = @regex.match(message).captures
    @on_message_callback.call(args)
  end

end

# somewhere else in the code, I find the class that I need...

MainAppModule.registered_extensions.each do |child|
    puts child.regex.inspect # this is nil and I dont want it to be
    if message =~ child.regex
      return child.exec(message)
    end
end

How can I design this so that the @regex will be set so I can access it within the loop?

I finally found a solution that works, and I have added now the whole code that is executable. Just store the code eg in file callexample.rb and call it by ruby callexample.rb

The main difference of my solution to the question is that the call to on_message now creates the instance with the relevant arguments and registers the created instance. Therefore I have deleted the method inherited because I don't need it any more.

I have added some puts statements to demonstrate in which order the code works.

class MainAppModule                               ## Added class
  @@registered_extensions = []
  def self.registered_extensions; @@registered_extensions; end
end

class ExtensionBase
  attr_reader :regex

  def self.on_message(string, &block)
    MainAppModule.registered_extensions << self.new(string, block)
  end

  def initialize(string, block)
    @regex = Regexp.new(string)
    @on_message_callback = block
  end

  def exec(message)
    args = @regex.match(message).captures
    @on_message_callback.call(args)
  end
end

class MyExtension < ExtensionBase

  on_message '/join (.+)' do |username|
    # this will be a callback function used later
    puts "Callback of #{self} called."
    "returnvalue"
  end
end

# somewhere else in the code, I find the class that I need...
MainAppModule.registered_extensions.each do |child|
    puts "Value of regex: #{child.regex}" # this is no more nil
    message = '/join something'
    if message =~ child.regex
      puts "On match evalue 'child.exec(message)' to: #{child.exec(message)}"
    end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM