SlideShare a Scribd company logo
COMMAND	LINE
APPLICATIONS	 	RUBY
Alexander	Merkulov
	/	

	merqlove @merqlove
DO_SNAPSHOT	CLI
A	command-line	snapshot	maker	for	DigitalOcean	droplets.
LOOKING	FOR	GEMS	&
Rake
OptionParser
Optitron
Commander
Main
...
manually
build	it	anywhere	else
BEST	PRACTICES
BASE	FEATURES	&	FACTS
COMPARISON
Feature OP Thor GLI
Number	of	downloads as	Ruby 63	596	500 898	088
Authors Community Y.	Katz D.	Copeland
No	runtime	dependencies Yes Yes Yes
The	argument	specification	and	the	code Yes Yes Yes
Output	an	option	summary Yes Yes Yes
Optional	and	mandatory	arguments Yes Yes Yes
Arguments	can	be	automatically	converted Yes Yes Yes
Arguments	can	be	restricted	to	a	certain	set Yes Yes Yes
ADVANCED	FEATURES	COMPARISON
Feature OP Thor GLI
Description	helper No Yes Yes
Long	description	helper No Yes Yes
Actions No Yes Yes/No
Subcommands No Yes Yes
Easy	Child	class	loading No Yes No
Minimalistic	application	codebase No Yes Yes/No
Actively	maintains Yes/No Yes Yes
Fancy	colors No Yes No
GIT-LIKE	INTERFACE	COMMAND	LINE	PARSER
	 	 	
Useful	if	you	work	on	monolith	binary.
Quite	readable	code.
No	OOP	required	:)
Has	scaffold	generator	with	TDD/BDD	approach.
Regular	updates.
GLI DAVETRON5000/GLI
$	gli	init	some	command	version├── Gemfile
├── README.rdoc
├── Rakefile
├── bin
│ └── some # our binary
├── dist # tools for deploy
├── features # if cucumber
│ ├── some.feature
│ ├── step_definitions
│ │ └── some_steps.rb
│ └── support
│ └── env.rb
├── lib
│ ├── some
│ │ └── version.rb
│ └── some.rb
├── some.gemspec
└── test
├── default_test.rb
└── test_helper.rb
ADD	SOME	COMMANDS
desc 'DEFAULT. Create and cleanup snapshot's'
command [:s, :snap] do |c|
c.desc 'Select api version.'
c.arg_name '1'
c.flag [:p,:protocol], default_value: 2, type: Numeric
c.desc 'How much snapshots you want to keep?'
c.arg_name '5'
c.flag [:k,:keep], default_value: 10, type: Numeric
...
c.desc 'Stop creating snapshots if maximum is reached.'
c.switch [:s,:stop]
c.action do |global_options,options,args|
DoSnapshot::Command.new(options).snap
end
end
desc 'Shows the version of the currently installed DoSnapshot gem'
version DoSnapshot::VERSION
gist
ADD	SOME	LOGIC
pre do |global,command,options,args|
$some_service = DoSnapshot::Service.new(options)
true
end
post do |global,command,options,args|
$some_service = nil
end
on_error do |exception|
$some_service.send(exception)
end
exit run(ARGV)
BUT	WHAT	WITH	ARRAY,	HASH
ARGUMENTS?

TIME	TO	TRY	:)
$ do_snapshot help
NAME
do_snapshot - `do_snapshot` able to create and cleanup snapshots on your droplets.
SYNOPSIS
do_snapshot [global options] command [command options] [arguments...]
GLOBAL OPTIONS
-c, --clean=arg - Cleanup snapshots after create. If you have more images than you want to `keep`, older will be deleted. (defa
-d, --delay=5 - Delay between snapshot operation status requests. (default: 10)
--digital_ocean_access_token=YOURLONGAPITOKEN - DIGITAL_OCEAN_ACCESS_TOKEN. if you can't use environment. (default: none)
--help - Show this message
-k, --keep=5 - How much snapshots you want to keep? (default: 10)
-l, --log=/Users/someone/.do_snapshot/main.log - Log file path. By default logging is disabled. (default: none)
-p, --protocol=1 - Select api version. (default: 2)
--smtp=user_name:yourmail@example.com - SMTP options. (default: none)
-q, --quiet=arg - Quiet mode. If don't need any messages and in console. (default: none)
-s, --stop=arg - Stop creating snapshots if maximum is reached. (default: none)
--timeout=250 - Timeout in sec's for events like Power Off or Create Snapshot. (default: 3600)
-v, --trace=arg - Verbose mode. (default: none)
COMMANDS
version - Shows the version of the currently installed DoSnapshot gem
help - Shows a list of commands or help for one command
s, snap - DEFAULT. Create and cleanup snapshot's
WHAT	ABOUT	TESTS?
RSpec/Minitest
Aruba
Cucumber
FEATURE	TEST
# features/some.feature
Feature: My bootstrapped app kinda works
In order to get going on coding my awesome app
I want to have aruba and cucumber setup
So I don't have to do it myself
Scenario: App just runs
When I get help for "some"
Then the exit status should be 0
# features/step_definitions/some_steps.rb
When /^I get help for "([^"]*)"$/ do |app_name|
@app_name = app_name
step %(I run `#{app_name} help`)
end
OPTIONS	&	ARGUMENTS
COMPARISON
Feature OP Thor GLI
Advanced	option	mode No Yes No
Multiple	options	one-liner No Yes No
Options	order No Yes No
Array	arguments No Yes Yes
Hash	arguments Yes/No Yes No
Enum	arguments No Yes No
Global(class-wide)	arguments No Yes No
CUSTOM	PARSERS	
accept Array do |value|
value.split(/s/).map(&:strip)
end
accept Hash do |value|
result = {}
value.split(/s/).each do |pair|
k,v = pair.split(/:/)
result[k] = v
end
result
end
...
desc 'SMTP options.'
arg_name 'user_name:yourmail@example.com'
flag :smtp, type: Hash
$ do_snapshot -k 5 --smtp=user_name:user1 password:123456
gist
Thor	is	a	toolkit	for	building	powerful	command-line
interfaces.	Widely	used.
Easy	to	split	monolith	application.
The	syntax	is	Rake-like.
Thor	is	more	than	just	option	parser	
A	lot	of	tutorials.
	THOR ERIKHUDA/THOR
bin
Binary	file(s)
dist
Rake	deploy	scripts
lib/*/runner
Application	runner
lib/*/cli
CLI	monolith	or	parent
lib/*/command
Command	interface
lib/*/log
Application	logger
spec
RSpec	tests	including
features	&	fixtures
├── bin
│ └── do_snapshot
├── dist
│ ├── ...
│ ├── gem.rake
│ ├── manifest.rake
│ └── zip.rake
├── lib
│ ├── do_snapshot
│ │ ├── cli.rb
│ │ ├── command.rbb
│ │ ├── log.rb
│ │ ├── runner.rb
│ │ └── ...
│ └── do_snapshot.rb
├── spec
│ ├── do_snapshot
│ │ └── ...
│ ├── fixtures
│ ├── support
│ │ ├── aruba.rb
│ │ └── ...
│ ├── do_snapshot_spec.rb
│ └── spec_helper.rb
├── Gemfile
├── README.md
├── Rakefile
└── do_snapshot.gemspec
BINARY
#!/usr/bin/env ruby
Signal.trap('INT') { exit 1 }
# resolve bin path, ignoring symlinks
require 'pathname'
bin_file = Pathname.new(__FILE__).realpath
# add self to libpath
$LOAD_PATH.unshift File.expand_path('../../lib', bin_file)
require 'do_snapshot/runner'
DoSnapshot::Runner.new(ARGV.dup).execute!
RUNNER
class Runner
def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel)
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
end
def execute!
exit_code = begin
run_cli
rescue StandardError => e
display_backtrace_otherwise(e)
rescue SystemExit => e
e.status
ensure
clean_before_exit
end
@kernel.exit(exit_code)
end
...
end
github
SAMPLE	CLI	MONOLITH
Sample	class	for	CLI
application.
map	-	mapping
commands.
initialize	-	prepare
environment.
no_commands	-	define
helper	or	private	methods. 	
module DoSnapshot
class CLI < Thor
include DoSnapshot::Helpers
default_task :snap
map %w( c s create ) => :snap
map %w( -V ) => :version
def initialize(*args)
super
# custom initialization
end
...
no_commands do
# define helpers
end
end
end
github
THOR	DSL
desc	-	description	&
shortcuts
long_desc	-
multiline	command
description.
method_option	-
command	option
	 desc 'c / s / snap / create', '...'
long_desc <<-LONGDESC
`do_snapshot` able to create snapshots ...
VERSION: #{DoSnapshot::VERSION}
LONGDESC
method_option :mail,
type: :hash,
aliases: %w( -m ),
banner: 'to:yourmail@example.com',
desc: 'Receive mail if fail or maximum is reached.'
def snap
...
end
github
METHOD_OPTION
aliases	—	A	list	of	aliases	for	option.	
banner	—	The	short	description	of	the	option,	printed	out
in	the	usage	description.
default	—	The	default	value	of	this	option	if	it	is	not
provided.
lazy_default	—	A	default	that	is	only	passed	if	the	cli
option	is	passed	without	a	value.
desc	—	A	description	for	the	option.	
required	—	Indicates	that	an	option	is	required
type	—	:string,	:hash,	:array,	:numeric,	or	:boolean
enum	—	A	list	of	allowed	values	for	this	option.
THOR	ACTIONS
say
ask
yes?
no?
add_file
...
copy_file
template
inside
run
TEST	TOOLS
RSpec
Aruba
Webmock
Rake
ARUBA	&	RSPEC	ARE	FRIENDS
# support/aruba.rb
require 'aruba/rspec'
require 'do_snapshot/runner'
Aruba.configure do |config|
config.command_launcher = :in_process
config.main_class = DoSnapshot::Runner
end
ARUBA	USEFUL	HELPERS
run
run_simple
all_stdout
all_stderr
all_output
expand_path
with_environment
ARUBA	WITHIN	RSPEC
RSpec.describe DoSnapshot::Runner, type: :aruba do
context 'commands' do
context '.help' do
it 'shows a help message' do
run 'do_snapshot help'
expect(all_stdout)
.to match('Commands:')
end
end
context '.version' do
it 'with right version' do
run 'do_snapshot version'
expect(all_stdout).to include(DoSnapshot::VERSION)
end
end
end
end
$ do_snapshot help s
Usage:
do_snapshot c / s / snap / create
Options:
-p, [--protocol=1] # Select api version.
# Default: 1
-o, [--only=123456 123456 123456] # Select some droplets.
-e, [--exclude=123456 123456 123456] # Except some droplets.
-k, [--keep=5] # How much snapshots you want to keep?
# Default: 10
-d, [--delay=5] # Delay between snapshot operation status requests.
# Default: 10
-m, [--mail=to:yourmail@example.com] # Receive mail if fail or maximum is reached.
-t, [--smtp=user_name:yourmail@example.com] # SMTP options.
-l, [--log=/Users/someone/.do_snapshot/main.log] # Log file path. By default logging is disabled.
-s, [--stop], [--no-stop] # Stop creating snapshots if maximum is reached.
-v, [--trace], [--no-trace] # Verbose mode.
-q, [--quiet], [--no-quiet] # Quiet mode. If don't need any messages and in console.
Description:
`do_snapshot` able to create and cleanup snapshots on your droplets.
CHECK	OUTPUT
Try
BEST	PRACTICES:
Deploy	to	repository	of	your	choice.
Use	single	Rake	task	for	pushing	to	any	service.
Provide	zip,	tgz	packs	of	your	CLI	app.
Use	Rubocop	&	Coverage	metrics.
Don't	be	too	lazy	to	write	tests.
Semantic	versioning.
Provide	docs	or/and	wiki.
...
So,	as	for	any	Ruby	application.
EXAMPLES	&	HOW-TO
github.com/chef/omnibus
github.com/mitchellh/vagrant
github.com/merqlove/do_snapshot
github.com/pseudomuto/bookery
Awesome	CommandLine	Apps
Thor	&	OptionParser	comparison.
HAPPY	CODING!
Thor
OptionParser	API
Aruba
RSpec
GLI
THANKS!
Q?
2015
	/		merqlove @merqlove

More Related Content

KEY
Aprendendo solid com exemplos
PDF
PHP traits, treat or threat?
PPTX
Introduction to Debuggers
ODP
What's new in Perl 5.10?
ODP
Java compilation
ODP
Mastering Namespaces in PHP
PDF
Erlangfactory
PPTX
Exploit Research and Development Megaprimer: Unicode Based Exploit Development
Aprendendo solid com exemplos
PHP traits, treat or threat?
Introduction to Debuggers
What's new in Perl 5.10?
Java compilation
Mastering Namespaces in PHP
Erlangfactory
Exploit Research and Development Megaprimer: Unicode Based Exploit Development

What's hot (20)

PDF
TMAPI 2.0 tutorial
ODP
Um2010
KEY
Speedy TDD with Rails
PDF
Modern Objective-C @ Pragma Night
PDF
Rocket Fuelled Cucumbers
PPTX
How Functions Work
PPTX
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
PDF
Configure once, run everywhere 2016
PDF
Connecting the Worlds of Java and Ruby with JRuby
PPTX
Exploit Research and Development Megaprimer: DEP Bypassing with ROP Chains
PPTX
Ruby3x3: How are we going to measure 3x
PDF
Intrinsic Methods in HotSpot VM
PPTX
Return Oriented Programming (ROP) Based Exploits - Part I
PDF
Dev Day 2019: Mike Sperber – Software Design für die Seele
PDF
Learning puppet chapter 3
PDF
The MetaCPAN VM for Dummies Part One (Installation)
PDF
Why scala is not my ideal language and what I can do with this
ODP
Extending Perl Critic
ODP
30 Minutes To CPAN
ODP
Open Source Compiler Construction for the JVM
TMAPI 2.0 tutorial
Um2010
Speedy TDD with Rails
Modern Objective-C @ Pragma Night
Rocket Fuelled Cucumbers
How Functions Work
Running Ruby on Solaris (RubyKaigi 2015, 12/Dec/2015)
Configure once, run everywhere 2016
Connecting the Worlds of Java and Ruby with JRuby
Exploit Research and Development Megaprimer: DEP Bypassing with ROP Chains
Ruby3x3: How are we going to measure 3x
Intrinsic Methods in HotSpot VM
Return Oriented Programming (ROP) Based Exploits - Part I
Dev Day 2019: Mike Sperber – Software Design für die Seele
Learning puppet chapter 3
The MetaCPAN VM for Dummies Part One (Installation)
Why scala is not my ideal language and what I can do with this
Extending Perl Critic
30 Minutes To CPAN
Open Source Compiler Construction for the JVM
Ad

Viewers also liked (7)

PPTX
Adventures of java developer in ruby world
PDF
Minitest
PDF
Making CLI app in ruby
PDF
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
PDF
Railsguide
KEY
Introducing Command Line Applications with Ruby
PDF
Developing cross platform desktop application with Ruby
Adventures of java developer in ruby world
Minitest
Making CLI app in ruby
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Railsguide
Introducing Command Line Applications with Ruby
Developing cross platform desktop application with Ruby
Ad

Similar to Command Line Applications with Ruby (20)

KEY
Crafting Beautiful CLI Applications in Ruby
KEY
Ruby and Rails Packaging to Production
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist this text should come
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist1112
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
TXT
Gemlist
Crafting Beautiful CLI Applications in Ruby
Ruby and Rails Packaging to Production
Gemlist
Gemlist
Gemlist
Gemlist
Gemlist this text should come
Gemlist
Gemlist
Gemlist
Gemlist
Gemlist
Gemlist1112
Gemlist
Gemlist
Gemlist
Gemlist
Gemlist
Gemlist
Gemlist

Recently uploaded (20)

PDF
Parts of Speech Prepositions Presentation in Colorful Cute Style_20250724_230...
DOC
学位双硕士UTAS毕业证,墨尔本理工学院毕业证留学硕士毕业证
PPTX
Non-Verbal-Communication .mh.pdf_110245_compressed.pptx
PPTX
Role and Responsibilities of Bangladesh Coast Guard Base, Mongla Challenges
PPTX
Presentation for DGJV QMS (PQP)_12.03.2025.pptx
PPTX
Project and change Managment: short video sequences for IBA
PPTX
Primary and secondary sources, and history
PPTX
Hydrogel Based delivery Cancer Treatment
PDF
Instagram's Product Secrets Unveiled with this PPT
DOCX
"Project Management: Ultimate Guide to Tools, Techniques, and Strategies (2025)"
PPTX
INTERNATIONAL LABOUR ORAGNISATION PPT ON SOCIAL SCIENCE
PPTX
Impressionism_PostImpressionism_Presentation.pptx
PPTX
Human Mind & its character Characteristics
PPTX
worship songs, in any order, compilation
PPTX
Learning-Plan-5-Policies-and-Practices.pptx
PPTX
Self management and self evaluation presentation
PPTX
Effective_Handling_Information_Presentation.pptx
PPTX
Relationship Management Presentation In Banking.pptx
PDF
Why Top Brands Trust Enuncia Global for Language Solutions.pdf
PPTX
Emphasizing It's Not The End 08 06 2025.pptx
Parts of Speech Prepositions Presentation in Colorful Cute Style_20250724_230...
学位双硕士UTAS毕业证,墨尔本理工学院毕业证留学硕士毕业证
Non-Verbal-Communication .mh.pdf_110245_compressed.pptx
Role and Responsibilities of Bangladesh Coast Guard Base, Mongla Challenges
Presentation for DGJV QMS (PQP)_12.03.2025.pptx
Project and change Managment: short video sequences for IBA
Primary and secondary sources, and history
Hydrogel Based delivery Cancer Treatment
Instagram's Product Secrets Unveiled with this PPT
"Project Management: Ultimate Guide to Tools, Techniques, and Strategies (2025)"
INTERNATIONAL LABOUR ORAGNISATION PPT ON SOCIAL SCIENCE
Impressionism_PostImpressionism_Presentation.pptx
Human Mind & its character Characteristics
worship songs, in any order, compilation
Learning-Plan-5-Policies-and-Practices.pptx
Self management and self evaluation presentation
Effective_Handling_Information_Presentation.pptx
Relationship Management Presentation In Banking.pptx
Why Top Brands Trust Enuncia Global for Language Solutions.pdf
Emphasizing It's Not The End 08 06 2025.pptx

Command Line Applications with Ruby