Search code examples
ruby-on-railsrubycommand-line-interfacethor

Thor: Class Variables are not working


I have the following test code.

require "thor"

module Snap
  class CLI < Thor
    desc 'login', 'Login Credentials'
    def login(user,pass)
      @username = user
      @password = pass
      say @password
    end

    desc 'block', 'Block user'
    def block(input)
      say @username
    end
  end
end

If I type Snap login abc xyz in my command line. I get the the output as xyz. But when I type Snap block a. The output i get is just a blank space. ie: nothing gets stored at username or password.

Why is this and how can I resolve this?


Solution

  • The problem is that the program is terminated in between two invocations of your command. Therefore, all state is lost and consequently the username is lost.

    In order to persist variables across multiple invocations of your command, you need to save it to a file. For example, you could save a hidden file in the user's home directory in the yaml format.

    CAUTION: be aware that this will store the password in plain text in the config file!

    require 'thor'
    require 'yaml'
    
    module Snap
      class CLI < Thor
        def initialize(*args)
          super
          read_config
        end
    
        desc 'login', 'Login Credentials'
        def login(user, pass)
          @username = user
          @password = pass
          say @password
          write_config
        end
    
        desc 'block', 'Block user'
        def block(input)
          say @username
        end
    
        private
    
        CONFIG_FILE = '~/.myprogram.conf'
    
        def write_config
          config = {}
          config['username'] = @username
          config['password'] = @password
          File.open(CONFIG_FILE, 'w') do |f|
            f.write config.to_yaml
          end
        end
    
        def read_config
          config = YAML.load_file(CONFIG_FILE)
          @username = config['username']
          @password = config['password']
        end
      end
    end