简体   繁体   中英

Accessing command line arguments from outside of Thor class

Pretty new to Ruby and OO. Studying the text books, and all the articles that google found on Thor.

I have Thor working to capture multiple command line arguments and options. I'd like to do the rest of my programming from outside the Cli < Thor class though, and am having trouble accessing the command line arguments from outside the Cli class.

Questions:

Q1. Can the Cli < Thor class be treated like any other ruby class, or does inheriting from Thor, or the "Cli.start" command, cripple certain functionality of the Cli class versus not using Thor? Asking because I may simply not know how to access an instance variable from outside a class that doesn't use the initialize method. Thor will not let me use the initialize method to bring in the command line variables, probably because initialize is a reserved method name in ruby.

Q2. How can I access the command line argument variables a and b from outside the Thor class?

Here's my code

#!/usr/bin/env ruby

require 'thor'

class Cli < Thor
  attr_reader :a, :b
  method_option :add, :type => :string, :desc => 'add servers'
  method_option :prod, :type => :string, :desc => 'production stack'

  desc "tier <stack folder name> <app | web>", "creates an app or web server tier for the stack"
  def tier(a,b)
    @a = a
    @b = b
    puts a
    puts b
  end
end

Cli.start

arguments = Cli.new

puts "the first argument is #{arguments.a}"

Here's the result. Close (maybe). No errors, but arguments.a is nil.

$ ./create.rb tier a b
a
b
the first argument is 

--

puts arguments.tier.a

threw the error:

./create.rb:11:in `tier': wrong number of arguments (0 for 2) (ArgumentError)
    from ./create.rb:23:in `<main>'

The following works without Thor and using an initialize method and attr_reader, straight out of the text books. Can't figure out how to access the variables from a non-initialize method though.

#!/usr/bin/env ruby

class Cli 
  attr_reader :a, :b
  def initialize(a,b)
    @a = a
    @b = b
  end
end

arguments = Cli.new("a","b")

puts arguments.a

outupt:

$ ./create_wo_thor.rb    
a

Instantiating your Cli class doesn't make much sense; that's not how Thor is designed.

You have a few options to access internal data from outside the class. If there are only a few variables that you want access to, storing them as class variables and making them available through getters (and setters, if you need them) would work:

require 'thor'

class Cli < Thor
  method_option :add, :type => :string, :desc => 'add servers'
  method_option :prod, :type => :string, :desc => 'production stack'

  desc "tier <stack folder name> <app | web>", "creates an app or web server tier for the stack"
  def tier(a,b)
    @@a = a
    @@b = b
    puts a
    puts b
  end

  def self.get_a
    @@a
  end

  def self.get_b
    @@b
  end
end

Cli.start

puts "the first argument is #{Cli.get_a}"

This works as you hope:

$ ./thor.rb tier a b                                                                                                                                                                                                   
a                                                                                                                                                                                                                                           
b                                                                                                                                                                                                                                           
the first argument is a

I prefer the following, using a global Hash:

require 'thor'

$args = {}

class Cli < Thor
  method_option :add, :type => :string, :desc => 'add servers'
  method_option :prod, :type => :string, :desc => 'production stack'

  desc "tier <stack folder name> <app | web>", "creates an app or web server tier for the stack"
  def tier(a,b)
    $args[:a] = a
    $args[:b] = b
    puts a
    puts b
  end
end

Cli.start

puts "the first argument is #{$args[:a]}"

Last, I'd be remiss not to point out that all the command line arguments are available in the global ARGV , anyway:

require 'thor'

class Cli < Thor
  method_option :add, :type => :string, :desc => 'add servers'
  method_option :prod, :type => :string, :desc => 'production stack'

  desc "tier <stack folder name> <app | web>", "creates an app or web server tier for the stack"
  def tier(a,b)
    puts a
    puts b
  end
end

Cli.start

puts "The first argugment is #{ARGV[1]}"

What would be best depends on how you intend to use it. If you just want raw access to the command line arguments, ARGV is the way to go. If you want to access certain pieces after Thor has done some processing for you, one of the first two might be more helpful.

Here's my code with all three options included for accessing the command line arguments from outside the Cli < Thor class. Compliments to Darshan.

#!/usr/bin/env ruby

require 'thor'
$args = {}

class Cli < Thor
  attr_reader :a, :b
  method_option :add, :type => :string, :desc => 'add servers'
  method_option :prod, :type => :string, :desc => 'production stack'

  desc "tier <stack folder name> <app | web>", "creates an app or web server tier for the stack"
  def tier(a,b)
    # store a and b in a global hash
    $args[:a] = a
    $args[:b] = b
    # store a and b in class variables 
    @@a = a
    @@b = b
  end

  # getter methods, for access of the class variables from outside the class
  def self.get_a
    @@a
  end
  def self.get_b
    @@b
  end
end

Cli.start

# three ways now to access the command line arguments from outside the Cli < Thor class
puts "the first argument, from $args[:a], is #{$args[:a]}"
puts "the second argument, from Cli.get_b, is #{Cli.get_b}"
puts "the first argument, from ARGV[1], is #{ARGV[1]}"

Results:

$ ./create.rb tier a b
the first argument, from $args[:a], is a
the second argument, from Cli.get_b, is b
the first argument, from ARGV[1], is a

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