在 Ruby 中使用菜单定义方法

Defining methods with menu in Ruby

提问人: 提问时间:2/24/2023 更新时间:2/24/2023 访问量:52

问:

我有这个代码只是为了演示我的问题。 如何将这三个命令分为三种不同的方法?而且我的想法是对的吗?我已经写好了菜单,我开始掌握 Ruby,所以我想了解更多。

require 'net/sftp'
require 'ostruct'
require 'optparse'

class Sftp
  
  def parse(arguments)
    ARGV << "-h" if ARGV.empty?
    @options = OpenStruct.new
    
    args = OptionParser.new do |args|
      args.banner = "Usage: #{__FILE__} [options]"
      
      args.on("-s", "--set-host=HOST", String,
         "The Host To Connect To") do |set_host|
         @options.set_host = set_host
      end
      
      args.on("-u", "--username=USERNAME", String,
         "Authenticate With A Username") do |username|
         @options.username = username
      end

      args.on("-p", "--password=PASSWORD", String,
         "Authenticate With A Password") do |password|
         @options.password = password
      end

      args.on("-w", "--wharf=WHARF", Integer,
         "Specify The Wharf (Port) The Service Is Running") do |wharf|
         @options.wharf = wharf
      end

      args.on("-m", "--mkdir=CREATE DIRECTORY", String,
         "Create A Directory") do |mkdir|
         @options.mkdir = mkdir
      end

      args.on("-h", "--help", "Show Help And Exit") do
        puts args
        exit
      end

    begin
      args.parse!(arguments)
    
    rescue OptionParser::MissingArgument => error
      puts "[!] ".red + error.message.bold
      exit

    rescue OptionParser::InvalidOption => error
      puts "[!] ".red + error.message.bold
      exit
   end

def connect(arguments)
  Net::SFTP.start(@options.set_host, @options.username, :password => @options.password, :port => @options.wharf) do |sftp|
    mkdir(sftp) if @options.mkdir         
  end

  output("Exiting at => (#{Time.now})")
end
  
def run(arguments)
  parse(arguments)
  connect(arguments)
end

private 

def mkdir(sftp)
  sftp.mkdir!(@options.mkdir)
  output("Creating Directory => #{@options.mkdir}")
end

def output(string)
      puts "----------------------------------------------------------"
      puts " #{string}"
      puts "----------------------------------------------------------"
      end
    end
  end
end

sftp = Sftp.new
sftp.run(ARGV)

这是完整的代码。我希望这已经足够清楚了。对不起,如果我不是很具体。

Ruby 方法 菜单 SFTP

评论


答:

1赞 spickermann 2/24/2023 #1

我的第一个重构步骤如下所示:

require 'net/sftp'
require 'ostruct'
require 'optparse'

class Sftp
  def run(arguments)
    parse(arguments)
    connect(arguments)
  end

  private

  def parse(arguments)
    ARGV << "-h" if ARGV.empty?
    @options = OpenStruct.new
    
    args = OptionParser.new do |args|
      args.banner = "Usage: #{__FILE__} [options]"
      
      args.on("-s", "--set-host=HOST", String, "The Host To Connect To") do |set_host|
        @options.set_host = set_host
      end
      
      args.on("-u", "--username=USERNAME", String, "Authenticate With A Username") do |username|
        @options.username = username
      end

      args.on("-p", "--password=PASSWORD", String, "Authenticate With A Password") do |password|
        @options.password = password
      end

      args.on("-w", "--wharf=WHARF", Integer, "Specify The Wharf (Port) The Service Is Running") do |wharf|
        @options.wharf = wharf
      end

      args.on("-m", "--mkdir=CREATE DIRECTORY", String, "Create A Directory") do |mkdir|
        @options.mkdir = mkdir
      end

      args.on("-h", "--help", "Show Help And Exit") do
        puts args
        exit
      end

      begin
        args.parse!(arguments)
      
      rescue OptionParser::MissingArgument => error
        puts "[!] ".red + error.message.bold
        exit

      rescue OptionParser::InvalidOption => error
        puts "[!] ".red + error.message.bold
        exit
      end
    end
  end

  def connect(arguments)
    Net::SFTP.start(@options.set_host, @options.username, :password => @options.password, :port => @options.wharf) do |sftp|
      mkddir(sftp) if @options.mkdir
      rmdir(sftp) if @options.rmdir
      erase(sftp) if @options.erase         
    end

    output("Exiting at => (#{Time.now})")
  end

  def mkdir(sftp)
    sftp.mkdir!(@options.mkdir)
    output("Creating Directory => #{@options.mkdir}")
  end

  def rmdir(sftp)
    sftp.rmdir!(@options.rmdir)     
    output("Deleting Directory => #{@options.rmdir}")
  end

  def erase(sftp)
    sftp.remove!(@options.erase)
    output("Deleting File => #{@options.erase}")
  end

  def output(string)
    puts "----------------------------------------------------------"
    puts " #{string}"
    puts "----------------------------------------------------------"
  end
end

sftp = Sftp.new
sftp.run(ARGV)

评论

0赞 2/24/2023
我刚刚尝试过,但现在我得到了private method 'run' called for #<Sftp:0x00007f5f57102170> (NoMethodError)
1赞 spickermann 2/24/2023
只需将类中的方法移动到关键字上方即可。例如,在方法和 .def runprivateconnectprivate
0赞 2/24/2023
@spikermann 很抱歉打扰了你,但最后一个问题。我这样做了,但现在我收到这个错误undefined method 'run' for #<Sftp:0x00007fa5d4dab3e0> (NoMethodError)
1赞 spickermann 2/24/2023
您没有在问题中发布完整的课程,因此这有点难以回答。但是我回答的所有方法和需要在课堂上。至少并且需要是公共的(在关键字上方定义),所有其他方法可能是私有的(在关键字下方定义)。StfprunSftpruninitializeprivateprivate
1赞 spickermann 2/24/2023
我把你的问题中的所有代码都包含在我的答案中。问题在于您定义了一些嵌套在解析方法定义中的方法。只要确保嵌套和缩进是正确的,在定义下一个方法之前,一个方法已经正确结束。