SlideShare una empresa de Scribd logo
1 de 33
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

Dev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die SeeleDev Day 2019: Mike Sperber – Software Design für die Seele
Dev Day 2019: Mike Sperber – Software Design für die Seele
DevDay Dresden
 
Open Source Compiler Construction for the JVM
Open Source Compiler Construction for the JVMOpen Source Compiler Construction for the JVM
Open Source Compiler Construction for the JVM
Tom Lee
 

La actualidad más candente (20)

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

Destacado (7)

Adventures of java developer in ruby world
Adventures of java developer in ruby worldAdventures of java developer in ruby world
Adventures of java developer in ruby world
 
Minitest
MinitestMinitest
Minitest
 
Making CLI app in ruby
Making CLI app in rubyMaking CLI app in ruby
Making CLI app in ruby
 
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
Slides with notes from Ruby Conf 2014 on using simple techniques to create sl...
 
Railsguide
RailsguideRailsguide
Railsguide
 
Introducing Command Line Applications with Ruby
Introducing Command Line Applications with RubyIntroducing Command Line Applications with Ruby
Introducing Command Line Applications with Ruby
 
Developing cross platform desktop application with Ruby
Developing cross platform desktop application with RubyDeveloping cross platform desktop application with Ruby
Developing cross platform desktop application with Ruby
 

Similar a Command Line Applications with Ruby

D Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance ProblemsD Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
MySQLConference
 
Владимир Перепелица "Модули"
Владимир Перепелица "Модули"Владимир Перепелица "Модули"
Владимир Перепелица "Модули"
Media Gorod
 

Similar a Command Line Applications with Ruby (20)

Deep learning - the conf br 2018
Deep learning - the conf br 2018Deep learning - the conf br 2018
Deep learning - the conf br 2018
 
AWS Lambda from the trenches
AWS Lambda from the trenchesAWS Lambda from the trenches
AWS Lambda from the trenches
 
Toolbox of a Ruby Team
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
 
Performance Profiling in Rust
Performance Profiling in RustPerformance Profiling in Rust
Performance Profiling in Rust
 
A Life of breakpoint
A Life of breakpointA Life of breakpoint
A Life of breakpoint
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
 
Trust, but verify | Testing with Docker Containers
Trust, but verify | Testing with Docker ContainersTrust, but verify | Testing with Docker Containers
Trust, but verify | Testing with Docker Containers
 
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance ProblemsD Trace Support In My Sql Guide To Solving Reallife Performance Problems
D Trace Support In My Sql Guide To Solving Reallife Performance Problems
 
Katello on TorqueBox
Katello on TorqueBoxKatello on TorqueBox
Katello on TorqueBox
 
2013.02.02 지앤선 테크니컬 세미나 - Xcode를 활용한 디버깅 팁(OSXDEV)
2013.02.02 지앤선 테크니컬 세미나 - Xcode를 활용한 디버깅 팁(OSXDEV)2013.02.02 지앤선 테크니컬 세미나 - Xcode를 활용한 디버깅 팁(OSXDEV)
2013.02.02 지앤선 테크니컬 세미나 - Xcode를 활용한 디버깅 팁(OSXDEV)
 
Debugging of (C)Python applications
Debugging of (C)Python applicationsDebugging of (C)Python applications
Debugging of (C)Python applications
 
Ruby Isn't Just About Rails
Ruby Isn't Just About RailsRuby Isn't Just About Rails
Ruby Isn't Just About Rails
 
Writing Rust Command Line Applications
Writing Rust Command Line ApplicationsWriting Rust Command Line Applications
Writing Rust Command Line Applications
 
New features in Ruby 2.5
New features in Ruby 2.5New features in Ruby 2.5
New features in Ruby 2.5
 
Perl - laziness, impatience, hubris, and one liners
Perl - laziness, impatience, hubris, and one linersPerl - laziness, impatience, hubris, and one liners
Perl - laziness, impatience, hubris, and one liners
 
Monitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTapMonitoring MySQL with DTrace/SystemTap
Monitoring MySQL with DTrace/SystemTap
 
Nodejs Performance Debug
Nodejs Performance DebugNodejs Performance Debug
Nodejs Performance Debug
 
Workshop: snap from zero to hero
Workshop: snap from zero to heroWorkshop: snap from zero to hero
Workshop: snap from zero to hero
 
Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3Domain Specific Languages In Scala Duse3
Domain Specific Languages In Scala Duse3
 
Владимир Перепелица "Модули"
Владимир Перепелица "Модули"Владимир Перепелица "Модули"
Владимир Перепелица "Модули"
 

Último

Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
amilabibi1
 
Unlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven Curiosity
Unlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven CuriosityUnlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven Curiosity
Unlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven Curiosity
Hung Le
 
Uncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac FolorunsoUncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac Folorunso
Kayode Fayemi
 
Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...
Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...
Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...
David Celestin
 
Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...
Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...
Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...
ZurliaSoop
 

Último (17)

Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
 
ICT role in 21st century education and it's challenges.pdf
ICT role in 21st century education and it's challenges.pdfICT role in 21st century education and it's challenges.pdf
ICT role in 21st century education and it's challenges.pdf
 
Unlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven Curiosity
Unlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven CuriosityUnlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven Curiosity
Unlocking Exploration: Self-Motivated Agents Thrive on Memory-Driven Curiosity
 
Uncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac FolorunsoUncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac Folorunso
 
Dreaming Marissa Sánchez Music Video Treatment
Dreaming Marissa Sánchez Music Video TreatmentDreaming Marissa Sánchez Music Video Treatment
Dreaming Marissa Sánchez Music Video Treatment
 
Dreaming Music Video Treatment _ Project & Portfolio III
Dreaming Music Video Treatment _ Project & Portfolio IIIDreaming Music Video Treatment _ Project & Portfolio III
Dreaming Music Video Treatment _ Project & Portfolio III
 
Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...
Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...
Proofreading- Basics to Artificial Intelligence Integration - Presentation:Sl...
 
Digital collaboration with Microsoft 365 as extension of Drupal
Digital collaboration with Microsoft 365 as extension of DrupalDigital collaboration with Microsoft 365 as extension of Drupal
Digital collaboration with Microsoft 365 as extension of Drupal
 
Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...
Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...
Jual obat aborsi Jakarta 085657271886 Cytote pil telat bulan penggugur kandun...
 
Report Writing Webinar Training
Report Writing Webinar TrainingReport Writing Webinar Training
Report Writing Webinar Training
 
SOLID WASTE MANAGEMENT SYSTEM OF FENI PAURASHAVA, BANGLADESH.pdf
SOLID WASTE MANAGEMENT SYSTEM OF FENI PAURASHAVA, BANGLADESH.pdfSOLID WASTE MANAGEMENT SYSTEM OF FENI PAURASHAVA, BANGLADESH.pdf
SOLID WASTE MANAGEMENT SYSTEM OF FENI PAURASHAVA, BANGLADESH.pdf
 
Zone Chairperson Role and Responsibilities New updated.pptx
Zone Chairperson Role and Responsibilities New updated.pptxZone Chairperson Role and Responsibilities New updated.pptx
Zone Chairperson Role and Responsibilities New updated.pptx
 
Introduction to Artificial intelligence.
Introduction to Artificial intelligence.Introduction to Artificial intelligence.
Introduction to Artificial intelligence.
 
My Presentation "In Your Hands" by Halle Bailey
My Presentation "In Your Hands" by Halle BaileyMy Presentation "In Your Hands" by Halle Bailey
My Presentation "In Your Hands" by Halle Bailey
 
in kuwait௹+918133066128....) @abortion pills for sale in Kuwait City
in kuwait௹+918133066128....) @abortion pills for sale in Kuwait Cityin kuwait௹+918133066128....) @abortion pills for sale in Kuwait City
in kuwait௹+918133066128....) @abortion pills for sale in Kuwait City
 
lONG QUESTION ANSWER PAKISTAN STUDIES10.
lONG QUESTION ANSWER PAKISTAN STUDIES10.lONG QUESTION ANSWER PAKISTAN STUDIES10.
lONG QUESTION ANSWER PAKISTAN STUDIES10.
 
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdfAWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
 

Command Line Applications with Ruby