nicolas_b
nicolas_b

Reputation: 169

Ruby - How share data between ClassMethod and Instance

I work on a structure of classes to realize a cli script.
And I would like create class method to register a command. When a register a command, I want automatically generate a getter for this.

So, I have this structure :

lib/my_lib/commands.rb
lib/my_lib/commands/setup_command.rb

And then content of file :

# lib/my_lib/commands.rb
method MyLib
  method Commands

    def self.included(base)
      base.extend(ClassMethods)
    end

    module ClassMethods
      def register_command(*opts)
        command = opts.size == 0 ? {} : opts.extract_options!
        ...
      end

      def register_options(*opts)
        options = opts.size == 0 ? {} : opts.extract_options!
        ...
      end
    end

    class AbstractCommand
      def name
        ...
      end

      def description
        ...
      end

      def run
        raise Exception, "Command '#{self.clas.name}' invalid"
      end
    end

  end
end
# lib/my_lib/commands/setup_command.rb
module MyLib
  module Commands
    class SetupCommand < AbstractCommand
      include MyLib::Commands

      register_command :name        => "setup",
                       :description => "setup the application"

      def run
        puts "Yeah, my command is running"
      end

    end
  end
end

That I want :

# my_cli_script

#!/usr/bin/env ruby
require 'my_lib/commands/setup_command'

command = MyLib::Commands::SetupCommand.new
puts command.name # => "setup"
puts command.description # => "setup the application"
puts command.run # => "Yeah, my command is running"

Upvotes: 1

Views: 137

Answers (1)

Deradon
Deradon

Reputation: 1787

I'd do it somehow like this:

class CommandDummy

  def self.register_command(options = {})
    define_method(:name)        { options[:name] }
    define_method(:description) { options[:name] }
  end

  register_command :name        => "setup",
                   :description => "setup the application"

  def run
    puts "Yeah, my command is running"
  end
end

c = CommandDummy.new
puts c.name          # => "setup"
puts c.description   # => "setup the application"

add:

Instead of opts.size == 0 you might use opts.empty?

edit:

Just played a bit

# NOTE: I've no idea where to use stuff like this!
class CommandDummy
  # Add methods, which returns a given String
  def self.add_method_strings(options = {})
    options.each { |k,v| define_method(k) { v } }
  end

  add_method_strings :name        => "setup",
                     :description => "setup the application",
                     :run         => "Yeah, my command is running",
                     :foo         => "bar"
end

c = CommandDummy.new
puts c.name          # => "setup"
puts c.description   # => "setup the application"
puts c.run           # => "Yeah, my command is running"
puts c.foo           # => "bar"

Upvotes: 1

Related Questions