1

我研究类结构以实现 cli 脚本。
我想创建类方法来注册命令。当注册一个命令时,我想为此自动生成一个 getter。

所以,我有这个结构:

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

然后文件内容:

# 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

我想要的:

# 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"
4

1 回答 1

1

我会这样做:

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"

添加:

而不是opts.size == 0你可以使用opts.empty?

编辑:

刚玩了一点

# 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"
于 2012-09-26T22:57:14.473 回答