Module: Loops::CLI::Options

Included in:
Loops::CLI
Defined in:
lib/loops/cli/options.rb

Overview

Contains methods to parse startup options, bootstrap application, and prepare #Loops::CLI class to run.

Examples:

Loops::CLI.parse(ARGV)

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

COMMANDS_HELP =
<<-HELP
Available commands:
    list                             List available loops (based on config file)
    start                            Start all loops except ones marked with disabled:true in config
    start loop1 [loop2]              Start only loops specified
    stop                             Stop daemonized loops monitor
    stats                            Print loops memory statistics
    debug loop                       Debug specified loop
    help                             Show this message
HELP
SPLIT_HELP_LINE =
"\n#{' ' * 37}"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#engineEngine (readonly)

Returns The loops engine instance.

Returns:

  • (Engine)

    The loops engine instance.



40
41
42
# File 'lib/loops/cli/options.rb', line 40

def engine
  @engine
end

#optionsHash<Symbol, Object> (readonly)

Returns The hash of (parsed) command-line options.

Returns:

  • (Hash<Symbol, Object>)

    The hash of (parsed) command-line options.



36
37
38
# File 'lib/loops/cli/options.rb', line 36

def options
  @options
end

Class Method Details

.included(base) ⇒ Object



14
15
16
# File 'lib/loops/cli/options.rb', line 14

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

Instance Method Details

#bootstrap!String

Application bootstrap.

Checks framework option passed and load application stratup files conrresponding to its value. Also intitalizes the Loops.default_logger variable with the framework’s default logger value.

Returns:

  • (String)

    the used framework name (rails, merb, or none).

Raises:



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/loops/cli/options.rb', line 211

def bootstrap!
  loops_env = ENV['LOOPS_ENV'] = options[:environment] if options[:environment]

  options[:require].each do |library|
    require library
  end

  case options[:framework]
    when 'rails'
      ENV['RAILS_ENV'] = loops_env

      # Bootstrap Rails
      require Loops.root + 'config/boot'
      require Loops.root + 'config/environment'

      # Loops default logger
      Loops.default_logger = Rails.logger
    when 'merb'
      require 'merb-core'

      ENV['MERB_ENV'] = loops_env

      # Bootstrap Merb
      Merb.start_environment(:adapter => 'runner', :environment => ENV['MERB_ENV'] || 'development')

      # Loops default logger
      Loops.default_logger = Merb.logger
    when 'none' then
      # Plain ruby loops
      Loops.default_logger = Loops::Logger.new($stdout)
    else
      raise InvalidFrameworkError, "Invalid framework name: #{options[:framework]}. Valid values are: none, rails, merb."
  end
  options.delete(:environment)
  options.delete(:framework)
end

#extract_command!String

Extracts command name from arguments.

Other parameters are stored in the :args option of the #options hash.

Returns:

  • (String)

    a command name passed.



153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/loops/cli/options.rb', line 153

def extract_command!
  options[:command], *options[:args] = args
  if options[:command].nil? || options[:command] == 'help'
    puts option_parser
    exit
  end

  unless command = find_command(options[:command])
    STDERR << option_parser
    exit
  end
  command
end

#guess_root_dirString

Detect the application root directory (contatining “app” subfolder).

Returns:

  • (String)

    absolute path of the application root directory.



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/loops/cli/options.rb', line 173

def guess_root_dir
  # Check for environment variable LOOP_ROOT containing
  # the application root folder
  return options[:root] = ENV['LOOPS_ROOT'] if ENV['LOOPS_ROOT']
  # Check root parameter
  return options[:root] if options[:root]

  # Try to detect root dir (should contain app subfolder)
  current_dir = Dir.pwd
  loop do
    if File.directory?(File.join(current_dir, 'app'))
      # Found it!
      return options[:root] = current_dir
    end

    # Move up the FS hierarhy
    pwd = File.expand_path(File.join(current_dir, '..'))
    break if pwd == current_dir # if changing the directory made no difference, then we're at the top
    current_dir = pwd
  end

  # Oops, not app folder found. Use the current dir as the root
  current_dir = Dir.pwd
  options[:root] = current_dir
end

#option_parserOptionParser

Returns an option parser configured with all options available.

Returns:

  • (OptionParser)

    an option parser instance.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/loops/cli/options.rb', line 48

def option_parser
  @option_parser ||= OptionParser.new do |opt|
    opt.banner = "Usage: #{File.basename($0)} command [arg1 [arg2]] [options]"
    opt.separator ''
    opt.separator COMMANDS_HELP
    opt.separator ''
    opt.separator 'Specific options:'

    opt.on('-c', '--config=file', 'Configuration file') do |config_file|
      options[:config_file] = config_file
    end

    opt.on('-d', '--daemonize', 'Daemonize when all loops started') do |value|
      options[:daemonize] = true
    end

    opt.on('-e', '--environment=env', 'Set RAILS_ENV (MERB_ENV) value') do |env|
      options[:environment] = env
    end

    opt.on('-f', '--framework=name', "Bootstraps Rails (rails - default value) or Merb (merb) before#{SPLIT_HELP_LINE}starting loops. Use \"none\" for plain ruby loops.") do |framework|
      options[:framework] = framework
    end

    opt.on('-l', '--loops=dir', 'Root directory with loops classes') do |loops_root|
      options[:loops_root] = loops_root
    end

    opt.on('-p', '--pid=file', 'Override loops.yml pid_file option') do |pid_file|
      options[:pid_file] = pid_file
    end

    opt.on('-r', '--root=dir', 'Root directory which will be used as a loops home dir (chdir)') do |root|
      options[:root] = root
    end

    opt.on('-Rlibrary', '--require=library', 'require the library before executing the script') do |library|
      options[:require] << library
    end

    opt.on_tail("-h", '--help', 'Show this message') do
      puts(opt)
      exit(0)
    end
  end
end

#parse_options!Hash

Parses startup options, bootstraps application, starts loops engine.

Method exits process when unknown option passed or invalid value specified.

Returns:

  • (Hash)

    a hash of parsed options.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/loops/cli/options.rb', line 103

def parse_options!
  @options = {
    :daemonize   => false,
    :config_file => 'config/loops.yml',
    :environment => nil,
    :framework   => 'rails',
    :loops_root  => 'app/loops',
    :pid_file    => nil,
    :root        => nil,
    :require     => [],
  }

  begin
    option_parser.parse!(args)
  rescue OptionParser::ParseError => e
    STDERR.puts e.message
    STDERR << "\n" << option_parser
    exit
  end

  # Root directory
  guess_root_dir
  Loops.root = options.delete(:root)
  Dir.chdir(Loops.root)

  # Config file
  Loops.config_file = options.delete(:config_file)
  # Loops root
  Loops.loops_root  = options.delete(:loops_root)

  @command = extract_command!
  options[:framework] = 'none' unless @command.requires_bootstrap?

  bootstrap!
  start_engine!

  # Pid file
  Loops.pid_file    = options.delete(:pid_file)

  @options
end

#start_engine!Engine

Initializes a loops engine instance.

Method loads and parses loops config file, and then initializes pid file path.

Returns:

  • (Engine)

    a loops engine instance.



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/loops/cli/options.rb', line 256

def start_engine!
  # Start loops engine
  @engine = Loops::Engine.new
  # If pid file option is not passed, get if from loops config ...
  unless options[:pid_file] ||= @engine.global_config['pid_file']
    # ... or try Rails' tmp/pids folder ...
    options[:pid_file] = if Loops.root.join('tmp/pids').directory?
      'tmp/pids/loops.pid'
    else
      # ... or use global system pids folder
      '/var/run/loops.pid'
    end
  end
  @engine
end