Questions about this topic? Sign up to ask in the talk tab.

Difference between revisions of "Ruby"

From NetSec
Jump to: navigation, search
(added more network libraries)
(Ensure)
 
(145 intermediate revisions by 3 users not shown)
Line 1: Line 1:
=Ruby=
+
'''Ruby''' is an [[interpreted languages|interpreted language]], dynamically, reflective, semi-Functional and Object Orientated scripting language written in [[C]]. Ruby is said to be semi-Functional because it supports higher-order functions (aka lambdas) and closures (aka blocks). Ruby was created by [http://en.wikipedia.org/wiki/Yukihiro_Matsumoto Yukihiro "Matz" Matsumoto] and was first released in 1995.
  
[http://www.ruby-lang.org Ruby] is an interpreted, dynamically, reflective, semi-Functional and Object Orientated scripting language. Ruby is said to be semi-Functional because it supports hire-order functions (aka lambdas) and closures (aka blocks). Ruby was created by [http://en.wikipedia.org/wiki/Yukihiro_Matsumoto Yukihiro "Matz" Matsumoto] and was first released in 1995.
+
Matz's goal was to combine powerful features from various other [[programming]] languages, to create a [[programming language]] maximized for developer happiness; as opposed to computational efficiency. Ruby's Object Model mirrors that of Smalltalk, the syntax shares some similarities with [[Bash]], [[Perl]], [[Python]], and the scoping rules for closures were taken from [[LISP]].
  
Matz's goal was to combine powerful features from various other programming languages, and create a programming language maximized for developer happiness; as opposed to computational efficiency. Ruby's Object Model mirrors that of Smalltalk, the syntax shares some similarities with Bash, Perl, Python, and the scoping rules for closures was taken from LISP. Some of Ruby's key features include:
+
<font size="-2">Special thanks to [[User:Postmodern|Postmodern]] and [[User:Ohdazed|Ohdazed]] for their contributions to this article.</font>
 +
= Basics =
  
* Terse syntax, with some similarities to Perl or Bash
+
== Development Environment ==
* Non-whitespace sensitive
+
* Installation
* [http://en.wikipedia.org/wiki/Duck_typing Duck Typing]
+
* Gems
* [http://en.wikipedia.org/wiki/Operator_overloading Operator Overloading]
+
* [http://en.wikipedia.org/wiki/Higher-order_function Higher-order functions] (aka lambdas)
+
* [http://en.wikipedia.org/wiki/Anonymous_function Anonymous functions] (aka closures or blocks)
+
* [http://en.wikipedia.org/wiki/Currying Currying]
+
* Fully Object Orientated. Everything is an Object, even primitives (<kbd>0x42.chr # => "A"</kbd>)
+
* Every statement has a return value
+
* Method-calls as messages
+
* Multiple inheritence via Modules (aka Mixins)
+
* [http://en.wikipedia.org/wiki/Metaclass Metaclasses]
+
* <kbd>if</kbd>, <kbd>elsif</kbd>, <kbd>else</kbd>, <kbd>unless</kbd>, <kbd>case</kbd>, <kbd>break</kbd>, <kbd>continue</kbd>, <kbd>retry</kbd>, <kbd>return</kbd>, <kbd>for ... in</kbd>, <kbd>while</kbd>, <kbd>until</kbd>, <kbd>begin</kbd>, <kbd>begin</kbd>, <kbd>raise</kbd>/<kbd>rescue</kbd>, <kbd>throw</kbd>/<kbd>catch</kbd> statements.
+
* In-line Regular Expressions (<kbd>"hello world" =~ /[a-z0-9]+/</kbd>)
+
* [http://en.wikipedia.org/wiki/Reflection_%28computer_programming%29 Reflection]
+
* [http://en.wikipedia.org/wiki/Metaprogramming Meta-programming]
+
* Open Classes (aka [http://en.wikipedia.org/wiki/Monkey_patch Monkey Patching])
+
* <kbd>method_missing</kbd>/<kbd>const_missing</kbd> methods
+
* [http://en.wikipedia.org/wiki/Continuation Continuations] (aka Fibers)
+
* Fully featured standard library
+
  
{{immediate|content}}
+
=== Interactive Ruby Console ===
  
==Learning==
+
IRB, or the Interactive Ruby Console, comes bundled with Ruby and allows you to interactively run code right from your command line. IRB can be invoked from your terminal simply by typing 'irb'.
  
There are free ebooks and websites which teach you how to program in Ruby:
+
» irb --help
 +
Usage:  irb.rb [options] [programfile] [arguments]
 +
  -f     Suppress read of ~/.irbrc
 +
  -m     Bc mode (load mathn, fraction or matrix are available)
 +
  -d                Set $DEBUG to true (same as `ruby -d')
 +
  -r load-module    Same as `ruby -r'
 +
  -I path          Specify $LOAD_PATH directory
 +
  --inspect     Use `inspect' for output (default except for bc mode)
 +
  --noinspect     Don't use inspect for output
 +
  --readline     Use Readline extension module
 +
  --noreadline     Don't use Readline extension module
 +
  --prompt prompt-mode
 +
  --prompt-mode prompt-mode
 +
    Switch prompt mode. Pre-defined prompt modes are
 +
    `default', `simple', `xmp' and `inf-ruby'
 +
  --inf-ruby-mode  Use prompt appropriate for inf-ruby-mode on emacs.
 +
    Suppresses --readline.
 +
  --simple-prompt  Simple prompt mode
 +
  --noprompt     No prompt mode
 +
  --tracer     Display trace for each execution of commands.
 +
  --back-trace-limit n
 +
    Display backtrace top n and tail n. The default
 +
    value is 16.
 +
  --irb_debug n     Set internal debug level to n (not for popular use)
 +
  -v, --version     Print the version of irb
  
* [http://tryruby.org/ TryRuby] in your browser!
+
<pre>
* [http://www.humblelittlerubybook.com/ The Humble Little Ruby Book]
+
$ irb
* [http://ruby-doc.org/docs/ProgrammingRuby/ Programming in Ruby (1.8): The Pragmatic Programmer's Guide]
+
irb(main):001:0>puts 'woot'
* [http://ruby.bastardsbook.com/ The Bastards Book of Ruby]
+
woot
* [http://rubylearning.com/ Learning Ruby] (blog)
+
=> nil
 +
irb(main):002:0>
 +
</pre>
  
Of course, there are many other commercial books and websites on Ruby:
+
Running irb --simple-prompt will provide you with a more basic looking Ruby shell.
  
* [http://www.amazon.com/gp/product/1934356085/ref=as_li_tf_tl?ie=UTF8&tag=redditrrubyco-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=1934356085 Programming Ruby 1.9: The Pragmatic Programmers’ Guide]
+
<pre>
* [http://www.amazon.com/gp/product/0596516177/ref=as_li_tf_tl?ie=UTF8&tag=redditrrubyco-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596516177 The Ruby Programming Language]
+
$ irb --simple-prompt
* [http://www.amazon.com/gp/product/1933988657/ref=as_li_qf_sp_asin_tl?ie=UTF8&tag=redditrrubyco-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=1933988657 Well Grounded Rubyist]
+
>> puts 'woot'
* [http://www.amazon.com/gp/product/0321584104/ref=as_li_tf_tl?ie=UTF8&tag=redditrrubyco-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0321584104 Eloquent Ruby]
+
woot
* [https://cooperpress.com/rubyreloaded Ruby Reloaded (online course)]
+
=> nil
* [https://rubyoffrails.com/ Ruby Off Rails (online course)]
+
</pre>
  
==Installing==
+
You can use either 'exit', 'quit', or 'irb_exit' to close IRB and return to your terminal.
 +
<pre>
 +
$ irb --simple-prompt
 +
>> exit
 +
$ # back in our terminal :D
 +
</pre>
  
All Linux distributions provide packages for Ruby, and other Ruby development tools:
+
=== RVM ===
 +
RVM is a handy utility that can be used to manage multiple Ruby version installations on the same operating system. It allows you to run multiple interpreters and gemsets with a simple way to switch between them.
  
Debian / Ubuntu:
+
https://rvm.io/
  
<pre>sudo apt-get install ruby1.9.1-full</pre>
+
=== Pry ===
  
RedHat / Fedora:
+
Pry is a Ruby gem that provides an alterative to IRB (Interactive Ruby Console) with additional functionality to dig down into Ruby code while you are coding. You can view the source-code of any Ruby method from within the interpreter. It also provides some cool extras like Gist integration, syntax highlighting, and command shell integration.
  
<pre>sudo apt-get install ruby ruby-dev irb rubygems</pre>
+
Pry Homepage: https://github.com/pry/pry/
  
Mac OS X systems ship with an older version of Ruby already installed, however you will want to use the latest version (current 1.9.3). The easiest way to install Ruby on a *nix platform, which does not provide an recent version of Ruby, is with the [https://rvm.io/ Ruby Version Manager (RVM)]. RVM is a set of bash scripts which can download, compile, install and update Ruby all within one's home directory.
+
== Your first program ==
  
<pre>curl -L https://get.rvm.io | bash -s stable --ruby</pre>
+
=== Code ===
 +
{{code|text=<source lang="ruby">#!/usr/bin/ruby
 +
puts "Hello world\n"</source>}}
  
==Alternate Implementations==
+
=== Style ===
  
The primary implementation of Ruby is known as MRI (Matz Ruby Implementation) or CRuby. However, like any other programming language, Ruby also has many alternate implementations.
+
While Ruby is not whitespace sensitive, all Rubyists share a certain style:
  
* [http://jruby.org/ JRuby]: Ruby implemented on the Java Virtual Machine (JVM). It may be slow to startup, but once running JRuby is extremely performant. Consider using JRuby for highly parallized/threaded programs.
+
<ol>
* [http://rubini.us Rubinius]: Ruby implemented on [http://llvm.org/ LLVM]. Rubinius has a small core of C++ that uses LLVM to interpret, compile and run Ruby code. The majority of Rubinius is actually written in Ruby, which makes the source-code extremely readable.
+
  <li>Indent code using <b>two spaces</b>.</li>
* [http://macruby.org/ MacRuby]: Ruby implemented on LLVM and Objective C. MacRuby can interface to any Mac OS X system library.
+
  <li>All code must be within 80 columns.</li>
* [http://www.ironruby.net/ IronRuby]: Ruby implemented ontop of the Microsoft .NET Dynamic Language Runtime (DLR).
+
  <li>Class/Module names must be capitialized and <kbd>CamelCased</kbd>.</li>
* [https://github.com/mruby/mruby/ MRuby]: A custom C implementation of Ruby, designed for embedded systems. MRuby seeks to compete with Lua.
+
  <li>Constants must be <kbd>UPPERCASED_AND_UNDERSCORED</kbd>.</li>
* [http://www.rubymotion.com/ Ruby Motion]: Uses MacRuby to compile Ruby to Objective C iOS apps.
+
  <li>Method/variable names must be in <kbd>snake_case</kbd>.</li>
* [http://ruboto.org/ Ruboto]: JRuby optimized for the Android platform.
+
</ol>
  
==Development Tools==
+
For a complete Ruby Style Guide, please see the [https://github.com/styleguide/ruby/ GitHub Ruby Style Guide].
  
<kbd>ruby</kbd> is the Ruby interpreter.
+
=== Explanation ===
  
<pre>$ ruby my_script.rb
 
$ ruby -Ilib bin/my_util</pre>
 
  
<kbd>irb</kbd> is the Ruby interactive console, similar to <kbd>python</kbd> or <kbd>perlconsole</kbd>. IRB also supports tab-completion, which can be enabled by adding <kbd>require 'irb/completion'</kbd> to your <kbd>~/.irbrc1</kbd> file.
+
== Variables ==
  
<pre>$ irb
+
===Local===
>> RUBY_VERSION
+
A local variable is a variable that can only be used within the block it was initialized in. It can be created by assigning an Object to a lowercase keyword.
=> "1.9.3"</pre>
+
  
<kbd>gem</kbd>, or better known as RubyGems, is the package manager for Ruby. RubyGems allows you to install Ruby libraries, or Gems, from [https://rubygems.org/ RubyGems.org]. Installed Gems can be loaded with the <kbd>require</kbd> method:
+
{{code|text=<source lang="ruby">
 +
foo = 'bar'
 +
</source>}}
  
<pre>$ gem install foo-bar
+
===Global===
$ irb
+
 
>> require 'foo/bar'
+
Global variables can be accessed from anywhere within the entire program. They can be created by prefixing your variable the the <kbd>$</kbd> symbol.
=> true</pre>
+
Editting the assignment of a global variable will change the status of that variable globally and is generally avoided when writing Ruby scripts; use class-variables or constants instead.
 +
{{code|text=
 +
<source lang="ruby">
 +
$woot = 1337
 +
</source>}}
 +
 
 +
===Instance Variables===
 +
 
 +
Instance variables begin with the '@' symbol. Accessing an uninitialzed instance will return the <kbd>nil</kbd> value.
 +
{{code|text=<source lang="ruby">
 +
>> @instance
 +
=> nil
 +
>> @instance = 'ohdae'
 +
=> "ohdae"
 +
</source>}}
 +
 
 +
Instance variables can also be defined at the Class/Module level:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> module Settings
 +
>>  @config = {:verbose => false}
 +
>>  def self.config; @config; end
 +
>> end
 +
=> Settings
 +
>> Settings.config
 +
=> {:verbose => false}
 +
</source>}}
 +
 
 +
===Class Variables===
 +
 
 +
Class variables are shared by all methods within a Class or Module. These are created by using two '@' symbols at the beginning of your variable.
 +
Trying to initialize a class variable outside of a class will throw an error.
 +
{{code|text=<source lang="ruby">
 +
>> @@classvar
 +
NameError: uninitialized class variable @@classvar in Object
 +
from (irb):5
 +
from :0
 +
>> class Blackhat
 +
>>  @@classvar = 'ohhai'
 +
>>  def self.classvar; @@classvar; end
 +
>> end
 +
=> Blackhat
 +
>> Blackhat.classvar
 +
=> "ohhai"
 +
</source>}}
 +
 
 +
===Predefined Variables===
 +
 
 +
Certain variables are pre-defined into Ruby. The values of these variables cannot be changed.
 +
 
 +
* <kbd>self</kbd>: Represents the current scope. Similar to <kbd>this</kbd> from [[Java]].
 +
* <kbd>nil</kbd>: The null object.
 +
* <kbd>true</kbd>: Boolean true.
 +
* <kbd>false</kbd>: Boolean false.
 +
 
 +
== Data Types ==
 +
 
 +
===Boolean Values===
 +
 
 +
Ruby defines two boolean values, <kbd>true</kbd> and <kbd>false</kbd>:
 +
{{code|text=<source lang="ruby">
 +
>> 1 == 1
 +
=> true
 +
>> 1 == 2
 +
=> false
 +
</source>}}
 +
 
 +
===Integers===
 +
 
 +
Ruby also provides Integer literals:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> 10
 +
=> 10
 +
>> 010 # octal
 +
=> 8
 +
>> 0x0a # hexadecimal
 +
=> 10
 +
>> 1_000_000 # short-hand for big values
 +
=> 1000000
 +
</source>}}
 +
 
 +
In Ruby, Integers are also Objects, which you can call methods on:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> 0x42.chr
 +
=> "A"
 +
</source>}}
 +
 
 +
===Floats===
 +
 
 +
Ruby also provides floating point decimal literals:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> 1.5
 +
=> 1.5
 +
>> 1.5e10
 +
=> 15000000000.0
 +
</source>}}
 +
 
 +
Floats are also Objects:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> 1.5.round
 +
=> 2
 +
</source>}}
 +
 
 +
=== Strings ===
 +
 
 +
Ruby supports String literals as well.
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> "hello world"
 +
=> "hello world"
 +
>> 'hello\nworld'
 +
=> "hello\\nworld"
 +
>> "2 + 2 = #{2 + 2}" # String embedding
 +
=> "2 + 2 = 4"
 +
>> %{one
 +
two
 +
three}
 +
=> "one\ntwo\nthree"
 +
</source>}}
 +
 
 +
Strings are also Objects in Ruby:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> "hello".reverse
 +
=> "olleh"
 +
</source>}}
 +
 
 +
=== Symbols ===
 +
 
 +
Symbols are like Strings, but used for keywords or identifiers:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> :verbose
 +
=> :verbose
 +
>> :verbose == 'verbose'
 +
=> false
 +
>> :verbose == :verbose
 +
=> true
 +
</source>}}
 +
 
 +
=== Regular Expressions ===
 +
 
 +
Ruby supports inline [[Regular_expressions|Regular Expressions]], or [http://rubydoc.info/stdlib/core/Regexp Regexps]. Regular Expressions can be used to match Strings:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> "1-555-3333" =~ /(\d-)?\d{3}-\d{4}/
 +
=> 0
 +
>> match = "Please call 1-555-3333".match(/(\d-)?\d{3}-\d{4}/)
 +
=> #<MatchData "1-555-3333" 1:"1-">
 +
>> match[0]
 +
=> "1-555-3333"
 +
</source>}}
 +
 
 +
Regexps can also be used to rewrite Strings:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> "hello world".gsub(/e/,'3').gsub(/o/,'0')
 +
=> "h3ll0 w0rld"
 +
</source>}}
 +
 
 +
=== Arrays ===
 +
 
 +
An [http://rubydoc.info/stdlib/core/Array Array] is a group of objects, very similar to lists in Python. The items or objects inside an array are indexed on a non-negative zero-index.
 +
The objects inside of a Ruby array can be any mixture of variables.
 +
Creating an array can be done in a few different ways. You do not need to specifically declare your variable as an array during initialization, for example
 +
if you give Ruby a list of comma separated values inside brackets, Ruby will recgonize this as an array and use it as such from that point forward.
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> my_array = []
 +
=> []
 +
>> array_three = ["item", 5, foo, "Item2", "Strings can go here too"]
 +
=> ["item", 5, "bar", "Item2", "Strings can go here too"]
 +
>> array_three[0]
 +
=> "item"
 +
>> array_three[1]
 +
=> 5
 +
>> array_with_default = Array.new(1)
 +
=> []
 +
>> array_with_default[0]
 +
=> 1
 +
>> filled_array = Array.new(5) { 0 }
 +
=> [0, 0, 0, 0, 0]
 +
</source>}}
 +
 
 +
You will notice the item 'foo' is printed as "bar" because we defined this earlier in this page.
 +
 
 +
=== Hashes or Associative Arrays ===
 +
 
 +
Ruby [http://rubydoc.info/stdlib/core/Hash Hashes] are similar to Arrays, except they require two objects for every item in the group. One of these objects is the 'key' and the other is the 'value'.
 +
This is very useful when you want to index items by some other than the array's zero-index. A hash also uses braces, instead of the brackets an array uses.
 +
{{code|text=<source lang="ruby">
 +
new_hash = {
 +
  :username  => 'admin',
 +
  :password  => 'letmein123',
 +
  :hostname  => 'blackhatacademy.org',
 +
  :service  => 'ssh'
 +
  :port      =>  22
 +
}
 +
</source>}}
 +
 
 +
You can use the key inside of brackets to return the value for that object.
 +
{{code|text=<source lang="ruby">
 +
>> new_hash[:username]
 +
=> 'admin'
 +
</source>}}
 +
 
 +
Iterate through a hash, returning each key matched with it's value
 +
{{code|text=<source lang="ruby">
 +
>> new_hash.each do |k, v|
 +
>>  puts "key: #{k}"
 +
>>  puts "value: #{v}"
 +
>> end
 +
key: port
 +
value: 22
 +
key: hostname
 +
value: blackhatacademy.org
 +
key: service
 +
value: ssh
 +
key: username
 +
value: admin
 +
key: password
 +
value: letmein123
 +
=> {:port=>22, :hostname=>"blackhatacademy.org", :service=>"ssh", :username=>"admin", :password=>"letmein123"}
 +
</source>}}
 +
 
 +
Hashes can also have default values:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> counter = Hash.new(0)
 +
=> {}
 +
>> counter[:foo] += 1
 +
=> 1
 +
>> counter[:bar] += 2
 +
=> 2
 +
>> counter
 +
=> {:foo=>1, :bar=>2}
 +
 
 +
>> require 'digest/md5'
 +
=> true
 +
>> md5s = Hash.new { |hash,key| hash[key] = Digest::MD5.hexdigest(key) }
 +
=> {}
 +
>> md5s['foo']
 +
=> "acbd18db4cc2f85cedef654fccc4a4d8"
 +
>> md5s['bar']
 +
=> "37b51d194a7513e45b56f6524f2d51f2"
 +
>> md5s
 +
=> {"foo"=>"acbd18db4cc2f85cedef654fccc4a4d8", "bar"=>"37b51d194a7513e45b56f6524f2d51f2"}
 +
</source>}}
 +
 
 +
=== Casting ===
 +
 
 +
Ruby is a dynamically typed language, so it doesn't have Static Types or Type-Casting. Instead it has methods which convert an Object into another format:
 +
 
 +
* <kbd>to_i</kbd>: Converts an Object to an Integer.
 +
* <kbd>to_f</kbd>: Converts an Object to a Float.
 +
* <kbd>to_s</kbd>: Converts an Object to a String.
 +
* <kbd>to_sym</kbd>: Converts an Object to a Symbol.
 +
* <kbd>to_a</kbd>: Converts an Object to an Array.
 +
* <kbd>to_set</kbd>: Converts an Object to a Set.
 +
 
 +
Ruby also provides top-level methods for coercing an Object into another type:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> Integer(1.5)
 +
=> 1
 +
>> Float(1)
 +
=> 1.0
 +
>> String(1.5)
 +
=> "1.5"
 +
>> Array(1)
 +
=> [1]
 +
>> Array(nil)
 +
=> []
 +
</source>}}
 +
 
 +
== Operators ==
 +
 
 +
=== Boolean ===
 +
 
 +
Ruby supports all the usual ANSI [[C]] boolean operators:
 +
{{code|text=<source lang="ruby">
 +
>> true && false # AND
 +
=> false
 +
>> true || false # OR
 +
=> true
 +
>> true ^ true # XOR
 +
=> false
 +
>> !true # NOT
 +
=> false
 +
</source>}}
 +
 
 +
The <kbd>&&</kbd>, <kbd>||</kbd>, <kbd>!</kbd> operators can also be used with non-Boolean values. In Ruby, everything is treated as <kbd>true</kbd>, except for <kbd>nil</kbd>. As a result of this, you can use the <kbd>||=</kbd> operator to lazily initialize variables:
 +
 
 +
{{code|text=<source lang="ruby">
 +
module Settings
 +
 
 +
  def self.path
 +
    @path ||= File.join(ENV['HOME'],'.foorc')
 +
  end
 +
 
 +
end
 +
</source>}}
 +
 
 +
=== Ternary Operator ===
 +
 
 +
Ruby supports the ternary operator, just like ANSI [[C]]:
 +
 
 +
{{code|text=<source lang="ruby">
 +
number >= 0 ? :integer : :negative
 +
</source>}}
 +
 
 +
=== Bitwise Manipulations ===
 +
{{main|Bitwise math}}
 +
Ruby supports all of the common ANSI [[C]] bit-wise operators:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> 0xff & 0x02 # AND
 +
=> 2
 +
>> 0x02 | 0x1  # OR
 +
=> 3
 +
>> 0x02 ^ 0x3  # XOR
 +
=> 1
 +
>> ~0x0        # inverse
 +
=> -1
 +
>> 0x1 << 2    # left-shift
 +
=> 4
 +
>> 0x3 >> 1    # right-shift
 +
=> 1
 +
</source>}}
 +
 
 +
== Statements ==
 +
 
 +
=== If ===
 +
 
 +
Like other scripting languages, Ruby supports <kbd>if</kbd> statements:
 +
 
 +
{{code|text=<source lang="ruby">
 +
if x > 10
 +
  puts 'greater than 10'
 +
elsif x == 10
 +
  puts 'equal to 10'
 +
else
 +
  puts 'less than 10'
 +
end
 +
</source>}}
 +
 
 +
<kbd>if</kbd> statements can also be written as one-liners:
 +
 
 +
{{code|text=<source lang="ruby">
 +
puts 'x is a negative number' if x < 0
 +
</source>}}
 +
 
 +
Ruby also provides an <kbd>unless</kbd> statement, which is equivalent to <kbd>if !expression</kbd>.
 +
 
 +
=== Case ===
 +
 
 +
=== Begin ===
 +
 
 +
=== Rescue ===
 +
 
 +
=== Ensure ===
 +
== Loops ==
 +
 
 +
=== For ===
 +
 
 +
Ruby supports for loops like any other language:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> for i in (1..10)
 +
>>  puts i
 +
>> end
 +
2
 +
3
 +
4
 +
5
 +
6
 +
7
 +
8
 +
9
 +
10
 +
</source>}}
 +
 
 +
Generally, you never need to use for loops, due to Ruby's excellent support for Enumerators.
 +
 
 +
=== While ===
 +
 
 +
Ruby also supports traditional while loops:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> queue = [1,2,3,4]
 +
=> [1, 2, 3, 4]
 +
>> while (i = queue.shift)
 +
>>  puts i
 +
>> end
 +
1
 +
2
 +
3
 +
4
 +
</source>}}
 +
 
 +
=== Until ===
 +
 
 +
The <kbd>until</kbd> loop is a short-hand for saying <kbd>while !expression</kbd>:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> queue = [1,2,3,4]
 +
=> [1, 2, 3, 4]
 +
>> until queue.empty?
 +
>>  puts queue.shift
 +
>> end
 +
1
 +
2
 +
3
 +
4
 +
</source>}}
 +
 
 +
=== Enumerators ===
 +
 
 +
Ruby has superb support for Enumerators, or Iterators.
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> (1..5).each { |i| puts i }
 +
1
 +
2
 +
3
 +
4
 +
5
 +
=> 1..5
 +
>> (1..5).first(2)                  # get the first two integers
 +
=> [1, 2]
 +
>> (1..5).any? { |i| i % 2 == 0 }    # are any even integers?
 +
=> true
 +
>> (1..5).all? { |i| i < 10 }        # are all integers less than 10?
 +
=> true
 +
>> (1..5).select { |i| i % 2 == 0 }  # select only even integers
 +
=> [2, 4]
 +
>> (1..5).map { |i| i * 2 }          # multiply every integer by two
 +
=> [2, 4, 6, 8, 10]
 +
</source>}}
 +
 
 +
These methods are defined by including the [http://rubydoc.info/stdlib/core/Enumerable Enumerable] module, and defining an <kbd>each</kbd> which enumerates over the elements of the Object:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> class PasswordBruter
 +
>>  include Enumerable
 +
>>  def initialize(start_word)
 +
>>    @start_word = start_word
 +
>>    @end_word  = ('x' * start_word.length)
 +
>>  end
 +
>>  def each
 +
>>    (@start_word..@end_word).each { |word| yield word }
 +
>>  end
 +
>> end
 +
=> PasswordBruter
 +
>> PasswordBruter.new("hello").each { |word| puts word }
 +
hello
 +
hellp
 +
hellq
 +
hellr
 +
hells
 +
hellt
 +
hellu
 +
hellv
 +
hellw
 +
hellx
 +
....
 +
</source>}}
 +
 
 +
== Global Methods ==
 +
 
 +
=== defined? ===
 +
 
 +
Checks if a Class, Module or Constant is defined:
 +
 
 +
{{code|text=<source lang="ruby">
 +
if defined?(RUBY_ENGINE)
 +
  puts "Running on #{RUBY_ENGINE}"
 +
end
 +
</source>}}
 +
 
 +
=== send ===
 +
 
 +
Allows you to call arbitrary methods:
 +
 
 +
{{code|text=<source lang="ruby">
 +
obj.send(method_name)
 +
</source>}}
 +
 
 +
=== throw / catch ===
 +
 
 +
<kbd>throw</kbd> / <kbd>catch</kbd>: Throw and Catch allows one to jump out of a scope. This is similar to long jmp in Assembly:
 +
 
 +
{{code|text=<source lang="ruby">
 +
def callback
 +
  catch(:abort, :success) do
 +
    puts 'yielding ...'
 +
    yield
 +
    puts 'completed!'
 +
  end
 +
end
 +
</source>}}
 +
 
 +
<pre>
 +
>> callback { puts 'in the callback' }
 +
yielding ...
 +
in the callback
 +
completed!
 +
=> :success
 +
>> callback { puts 'aborting!'; throw :abort, :failed }
 +
=> :failed
 +
</pre>
 +
 
 +
=== raise ===
 +
 
 +
Raises an exception:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> raise("error!")
 +
RuntimeError: error!
 +
from (irb):38
 +
>> raise(ArgumentError,"invalid argument")
 +
ArgumentError: invalid argument
 +
from (irb):39
 +
</source>}}
 +
 
 +
== User Input ==
 +
 
 +
=== STDIN / STDOUT / STDERR ===
 +
 
 +
Ruby provides the <kbd>STDIN</kbd>, <kbd>STDOUT</kbd> and <kbd>STDERR</kbd> [http://rubydoc.info/stdlib/core/IO IO] constants. You can use these constants to read-input or print output.
 +
 
 +
{{code|text=<source lang="ruby">
 +
STDOUT.print "Password: "
 +
 
 +
password = STDIN.readline
 +
 
 +
if password.length < 6
 +
  STDERR.puts "Password was too short!"
 +
  exit -1
 +
else
 +
  puts "You entered: #{password}"
 +
end
 +
</source>}}
 +
 
 +
As you've probably guess, top-level IO methods, such as <kbd>puts</kbd> and <kbd>readline</kbd>, simply call to <kbd>STDOUT</kbd> or <kbd>STDIN</kbd>.
 +
 
 +
Ruby also provides the <kbd>$stdin</kbd>, <kbd>$stdout</kbd>, <kbd>$stderr</kbd> global variables, which allows you to hook/redirect all input/output. It's generally a good idea to use these global variables, instead of the constants.
 +
 
 +
=== Command-line Arguments ===
 +
 
 +
All command-line arguments are exposed via the <kbd>ARGV</kbd> constant.
 +
 
 +
{{code|text=<source lang="ruby">
 +
#!/usr/bin/env ruby
 +
puts "You passed the following arguments:"
 +
ARGV.each { |arg| puts "  #{arg}" }
 +
</source>}}
 +
 
 +
Ruby also provides an <kbd>ARGF</kbd> which is the [http://rubydoc.info/stdlib/core/File File] for the first file-argument:
 +
 
 +
{{code|text=<source lang="ruby">
 +
#!/usr/bin/env ruby
 +
 
 +
unless ARGV[0]
 +
  $stderr.puts "usage: #{$0} FILE"
 +
  exit -1
 +
end
 +
 
 +
ARGF.each_line do |line|
 +
  # ...
 +
end
 +
</source>}}
 +
 
 +
If you need to parse command-line options, use the built-in [http://rubydoc.info/stdlib/optparse/OptionParser OptionParser] library.
 +
 
 +
=== Environment Variables ===
 +
 
 +
You can access and set Environment Variables via the <kbd>ENV</kbd> Hash:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> ENV['HOME']
 +
=> "/home/blackhatacademy"
 +
</source>}}
 +
 
 +
== User-defined ==
 +
=== Methods ===
 +
 
 +
A simple hello world method:
 +
 
 +
{{code|text=<source lang="ruby">
 +
 
 +
def hello_world
 +
  puts "Hello, World!"
 +
end
 +
</source>}}
 +
 
 +
When calling a method that takes an argument, the parenthesis around the argument are optional.
 +
 
 +
{{code|text=<source lang="ruby">
 +
def hello(name)
 +
  puts "Hello, #{name}!"
 +
end
 +
 
 +
>> hello('ohdae')
 +
Hello, ohdae!
 +
=> nil
 +
>> hello 'ohdae'
 +
Hello, ohdae!
 +
=> nil
 +
</source>}}
 +
 
 +
Methods with default arguments:
 +
 
 +
{{code|text=<source lang="ruby">
 +
def hello(name='ohdae')
 +
  puts "Hello, #{name}!"
 +
end
 +
 
 +
>> hello
 +
Hello, ohdae!
 +
=> nil
 +
>> hello 'world'
 +
Hello, world!
 +
=> nil
 +
</source>}}
 +
 
 +
 
 +
Prematurely returning from a method:
 +
 
 +
{{code|text=<source lang="ruby">
 +
def add(arg1, arg2)
 +
  return nil unless arg1
 +
  return nil unless arg2
 +
 
 +
  arg1.to_i + arg2.to_i
 +
end</source>}}
 +
 
 +
Note, that we don't have to specify a return on the last line of our <kbd>add</kbd> method. This is because in Ruby, every statement has a return value, and the last-statement of a method is it's default return value.
 +
 
 +
=== Classes ===
 +
 
 +
Classes have names which must start in capital letters.
 +
 
 +
{{code|text=<source lang="ruby">
 +
class MyClass
 +
 
 +
end
 +
</source>}}
 +
 
 +
Classes can also inherit from other Classes:
 +
 
 +
{{code|text=<source lang="ruby">
 +
class MyOtherClass < MyClass
 +
 
 +
end
 +
</source>}}
 +
 
 +
In Ruby, the constructor method is called <kbd>initialize</kbd>:
 +
 
 +
{{code|text=<source lang="ruby">
 +
class MyClass
 +
  def initialize
 +
    puts "Hello\n"
 +
  end
 +
end
 +
</source>}}
 +
 
 +
Reader/writer methods for variables can also be defined within the class:
 +
 
 +
{{code|text=<source lang="ruby">
 +
class MyClass
 +
 
 +
  # defines a foo method
 +
  attr_reader :foo
 +
 
 +
  # defines a foo= method
 +
  attr_writer :bar
 +
 
 +
  # defines foo and foo= methods
 +
  attr_accessor :baz
 +
 
 +
  def initialize(foo,bar,baz)
 +
    @foo, @bar, @baz = foo, bar, baz
 +
  end
 +
end
 +
</source>}}
 +
 
 +
=== Modules ===
 +
 
 +
Modules are a way to group methods together, which can be included into multiple Classes. Modules allow you to compartmentalize common behaviours.
 +
 
 +
{{code|text=<source lang="ruby">
 +
module HasName
 +
  attr_accessor :name
 +
 
 +
  def initialize(name)
 +
    @name = name
 +
  end
 +
 
 +
  def named?(other_name)
 +
    @name == other_name
 +
  end
 +
 
 +
  def to_s
 +
    @name.to_s
 +
  end
 +
 
 +
end
 +
 
 +
class Person
 +
 
 +
  include HasName
 +
 
 +
end
 +
 
 +
class Computer
 +
 
 +
  include HasName
 +
 
 +
  def initialize(ip,name)
 +
    @ip = ip
 +
   
 +
    super(name)
 +
  end
 +
 
 +
end
 +
</source>}}
 +
 
 +
= Helpful Libraries =
 +
 
 +
Ruby's [http://rubydoc.info/stdlib/ stdlib] provides many useful libraries.
 +
 
 +
=== Struct ===
 +
 
 +
[http://rubydoc.info/stdlib/core/Struct Struct] allows one to easily create Classes with specific attributes:
 +
 
 +
{{code|text=<source lang="ruby">
 +
class Point < Struct.new(:x, :y)
 +
end
 +
</source>}}
 +
 
 +
<pre>
 +
>> p1 = Point.new(10, 20)
 +
=> #<struct Point x=10, y=20>
 +
>> p1.x
 +
=> 10
 +
>> p1.x += 20
 +
=> 30
 +
</pre>
 +
 
 +
=== OpenStruct ===
 +
 
 +
[http://rubydoc.info/stdlib/ostruct/OpenStruct OpenStruct] is like Struct, but allows for arbitrary attributes:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> require 'ostruct'
 +
=> true
 +
>> config = OpenStruct.new
 +
=> #<OpenStruct>
 +
>> config.x = 10
 +
=> 10
 +
>> config.name = 'foo'
 +
=> "foo"
 +
>> config.bla
 +
=> nil
 +
</source>}}
 +
 
 +
=== Set ===
 +
 
 +
[http://rubydoc.info/stdlib/set/Set Set] is like an Array, but does not allow duplicates:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> require 'set'
 +
=> true
 +
>> s = Set[]
 +
=> #<Set: {}>
 +
>> s << 1
 +
>> s << 2
 +
>> s << 2
 +
>> s << 3
 +
=> #<Set: {1, 2, 3}>
 +
</source>}}
 +
 
 +
=== Base64 ===
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> require 'base64'
 +
=> true
 +
>> Base64.encode64("hello")
 +
=> "aGVsbG8=\n"
 +
>> Base64.decode64("c2VjcmV0\n")
 +
=> "secret"
 +
</source>}}
 +
 
 +
=== Digest ===
 +
 
 +
The [http://rubydoc.info/stdlib/digest Digest] module, provides classes for computing Cryptographic Hashes, such as MD5 and SHA256:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> require 'digest/md5'
 +
=> true
 +
>> Digest::MD5.hexdigest("hello")
 +
=> "5d41402abc4b2a76b9719d911017c592"
 +
>> require 'digest/sha2'
 +
=> true
 +
>> Digest::SHA256.file('linux.iso')
 +
=> "5a7eb8f97a196583530812132ef98fe9"
 +
</source>}}
 +
 
 +
=== JSON ===
 +
 
 +
Ruby also provides a [http://rubydoc.info/stdlib/json JSON] serialization and parsing library:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> require 'json'
 +
=> true
 +
>> JSON.parse("[1,2]")
 +
=> [1, 2]
 +
>> {1 => 2, 2 => 3}.to_json
 +
=> "{\"1\":2,\"2\":3}"
 +
</source>}}
 +
 
 +
=== Queue ===
 +
 
 +
=== Sockets ===
 +
 
 +
Simple TCP server:
 +
 
 +
{{code|text=<source lang="ruby">
 +
require 'socket'
 +
 
 +
server = TCPServer.new 4444          # Binds to TCP port 4444
 +
 
 +
loop do                              # Starts a loop to wait for connection
 +
  client = server.accept            # Receive and accept client connection
 +
  client.puts "Hack The Planet!"    # Send data to client
 +
  client.close
 +
end
 +
</source>}}
 +
 
 +
Simple TCP client:
 +
 
 +
{{code|text=<source lang="ruby">
 +
require 'socket'
 +
 
 +
client = TCPSocket.new 'localhost', 4444      # Open TCP connection to localhost on port 4444
 +
 
 +
while line = client.gets                      # Read input from the socket connection
 +
  puts line                                  # Prints the input we captured with s.gets
 +
end                                     
 +
 
 +
client.close                                  # Closes the socket
 +
</source>}}
 +
 
 +
=== URI ===
 +
 
 +
The [http://rubydoc.info/stdlib/uri URI] library handles parsing and crafting of URIs:
 +
 
 +
{{code|text=<source lang="ruby">
 +
>> require 'uri'
 +
=> true
 +
>> uri = URI("http://www.blackhatlibrary.net/index.php?title=Ruby&action=edit&section=42")
 +
=> #<URI::HTTP:0x000000010e2080 URL:http://www.blackhatlibrary.net/index.php?title=Ruby&action=edit&section=42>
 +
>> uri.host
 +
=> "www.blackhatlibrary.net"
 +
>> uri.port
 +
=> 80
 +
>> uri.query
 +
=> "title=Ruby&action=edit&section=42"
 +
</source>}}
 +
 
 +
=== Net::HTTP ===
  
<kbd>ri</kbd> is a Ruby Documentation indexing tool. RI allows you to quickly looking documentation for Ruby methods, from the command line:
+
=== open-uri ===
  
<pre>$ ri Array#pack</pre>
+
[http://rubydoc.info/stdlib/open-uri/OpenURI open-uri] allows one to open URLs as temporary files:
  
<kbd>rake</kbd> is like Make, but for Ruby. Rake is used by Ruby projects to automate various tasks, such as testing, building or installing the project.
+
{{code|text=<source lang="ruby">
 +
>> require 'open-uri'
 +
=> true
 +
>> page = open(URI("http://www.blackhatlibrary.net/"))
 +
=> #<File:/tmp/open-uri20120812-2361-143dlvc>
 +
</source>}}
  
<pre>$ rake build</pre>
+
== Gems ==
  
[http://gembundler.com/ Bundler] is a RubyGem that allows projects to lock-down their dependencies. Bundler is commonly used by developers to automatically install dependencies for a project (<kbd>bundle install</kbd>) or to generate new projects (<kbd>bundle gem foo</kbd>).
+
Gems are packaged Ruby libraries and scripts. Anyone can create their [http://guides.rubygems.org/make-your-own-gem/ own gem] and publish it to https://rubygems.org.
  
[http://rspec.info/ RSpec] is a popular testing framework for Ruby. When a project grows beyond one file/Class/Module, it's generally a good idea to write tests for your code, to ensure nothing breaks.
+
Gems are installed using the <kbd>gem install</kbd>:
  
==Useful Libraries==
+
<pre>$ gem install foo-bar</pre>
  
For a complete listing of popular RubyGems by category, please see the [https://www.ruby-toolbox.com/ Ruby Toolbox].
+
Once installed, you can require the gem:
  
===Console===
+
{{code|text=<source lang="ruby">require 'foo/bar'</source>}}
  
* [https://github.com/janlelis/irbtools irbtools]: Pimp out your IRB.
+
=== Nokogiri ===
* [https://github.com/cldwalker/ripl Ripl]: Mimimal alternative to IRB, with tons of [http://rubygems.org/search?utf8=%E2%9C%93&query=ripl- plugins].
+
* [http://pryrepl.org/ Pry]: Powerful alternative to IRB.
+
  
===Database===
+
[http://nokogiri.org/ Nokogiri] is a fast XML/[[HTML]] parser built ontop of libxml.
  
* [http://sequel.rubyforge.org/ Sequel]: A SQL library for Ruby. Supports SQLite3, MySQL and Postgres.
+
Installing on Debian / Ubuntu:
* [http://datamapper.org/ DataMapper]: An Object Relational Mapper (ORM). Supports SQLite3, MySQL, Postgres, Oracle, MSSQL, HSQL, MongoDB, Redis.
+
* [http://ar.rubyonrails.org/ ActiveRecord]: The Object Relational Mapper (ORM) of Ruby on Rails.
+
* [http://mongomapper.com/ MongoMapper]: An Object Relational Mapper (ORM) for the [http://www.mongodb.org/ MongoDB].
+
  
===Binary===
+
<pre>$ sudo apt-get install libxml2-dev libxslt1-dev
 +
$ gem install nokogiri</pre>
  
* [https://github.com/ffi/ffi#readme FFI]: Foreign Function Interface for Ruby. Allows you to write bindings to C libraries, entirely in Ruby.
+
Installing on RedHat / Fedora:
* [http://metafuzz.rubyforge.org/binstruct/ BinStruct]: Binary Structures.
+
* [https://github.com/emonti/rstruct RStruct]: Yet another Ruby Binary Structure library.
+
* [https://github.com/sophsec/ffi-udis86#readme ffi-udis86]: Ruby FFI bindings to the [http://udis86.sourceforge.net/ udis86] dissassembler.
+
  
===Exploitation===
+
<pre>$ sudo yum install libxml2-devel libxslt-devel
 +
$ gem install nokogiri</pre>
  
* [https://github.com/hammackj/rex REX]: Various Exploitation helper methods, extracted from Metasploit.
+
{{code|text=<source lang="ruby">
* [https://github.com/emonti/rbkb Ruby BlackBag (rbkb)]: Ruby BlackBag. Misc ruby-based pen-testing/reversing tools. Inspired by Matasano BlackBag.
+
require 'nokogiri'
* [https://github.com/tduehr/ragweed Ragweed]: scriptable Win32/Linux/OSX debugger written in Ruby.
+
require 'open-uri'
* [https://github.com/struct/Nerve Nerve]: a cross platform hit tracer built on Ragweed.
+
* [http://ronin-ruby.github.com/ Ronin]: A Ruby platform for vulnerability research and exploit development. Ronin allows for the rapid development and distribution of code, Exploits, Payloads, Scanners, etc, via Repositories. Provides a customized Ruby Console, built-in Database and many useful classes, modules, methods, libraries.
+
  
===Network===
+
doc = Nokogiri::HTML(open("http://www.reddit.com/"))
  
* [https://github.com/todb/packetfu packetfu]: A library for reading a writing packets to an interface or to a libpcap-formatted file.
+
doc.search("div.entry a.title").each do |link|
* [http://rubyeventmachine.com/ EventMachine]: Evented IO for Ruby.
+
  puts link.attributes['href']
* [https://github.com/igrigorik/em-proxy em-proxy]: EventMachine TCP proxy.
+
end
* [http://rubygems.org/gems/net-dns net-dns]: DNS client library for Ruby.
+
</source>}}
* [http://rubygems.org/gems/whois whois]: Whois client for Ruby.
+
  
===Scanners / Spiders===
+
=== Sequel ===
  
* [https://github.com/sophsec/ruby-nmap#readme ruby-nmap]: Automate nmap from Ruby.
+
[http://sequel.rubyforge.org/ Sequel] is a low-level [[SQL]] library for '''Ruby'''. It allows you to query tables and insert data, all without having to write raw SQL. Sequel supports SQLite3, [[MySQL]], [[PostgreSQL]], [[Oracle]], etc.
* [https://github.com/postmodern/spidr#readme Spidr]: A versatile Web Spider. Spidr is designed to be fast and easy to use.
+
* [http://anemone.rubyforge.org/ Anemone]: A multi-threaded Web Spider, supporting various backend databases.
+
* [http://arachni-scanner.com/ Arachni]: Fully featured Web Vulnerability scanner.
+
  
===Web===
+
Installing on Debian / Ubuntu:
  
* [http://nokogiri.org/ Nokogiri]: A fast XML/HTML parser built ontop of libxml. Supports XPath and CSS-path searching of documents.
+
<pre>$ sudo apt-get install libsqlite3-dev
* [http://mechanize.rubyforge.org/ Mechanize]: Automated head-less browser.
+
$ gem install sqlite3-ruby sequel</pre>
* [https://github.com/archiloque/rest-client RestClient]: A simple HTTP client library.
+
* [https://github.com/postmodern/gscraper#readme GScraper]: Web-scraping interface to Google Search.
+
* [https://github.com/emonti/buby Buby]: JRuby bindings to [http://www.portswigger.net/burp/proxy.html Burp].
+
* [http://sinatrarb.org/ Sinatra]: A minimal library for creating web applications.
+
  
==Resources==
+
Installing on RedHat / Fedora:
  
* [irc://irc.freenode.net/#ruby-lang #ruby-lang on irc.freenode.net]
+
<pre>$ sudo yum install sqlite-devel
* [http://reddit.com/r/ruby /r/ruby]: A sub-reddit for news and questions about Ruby.
+
$ gem install sqlite3-ruby sequel</pre>
* [https://github.com/ GitHub]: where the majority of Ruby projects are hosted and developers collaborate.
+
* [https://rubygems.org RubyGems.org]: repository for all Ruby libraries)
+
* [https://www.ruby-toolbox.com/ Ruby Toolbox]: Groups popular RubyGems by category.
+
* [http://rubydoc.info/ RubyDoc]: Hosts documentation for Ruby [http://rubydoc.info/stdlib/core core], [http://rubydoc.info/stdlib/ stdlib] and all [http://rubydoc.info/gems/ RubyGems].
+
  
===References===
+
{{code|text=<source lang="ruby">
 +
require 'sequel'
  
* [http://guides.rubygems.org/make-your-own-gem/ Make your own gem]: Basic guide on publishing your first RubyGem.
+
DB = Sequel.sqlite('file.sqlite3')
* [http://gitref.org/ GitRef]: Reference to Git, the Distributed Version Control System (DVCS) prefered by Rubyists.
+
DB.create_table(:mytable) do
* [https://github.com/styleguide/ruby/ Ruby Style Guide]: The defacto Ruby style-guide.
+
  integer: id
 +
  varchar: name, :length => 256
 +
end
  
===Talks===
+
DB[:mytable].insert(1, "foo")
 +
DB[:mytable].insert(2, "bar")
 +
DB[:mytable].where(:name => 'bar')
 +
</source>}}
  
* [http://blip.tv/rupy-strongly-dynamic-conference/yehuda-katz-tradeoffs-and-choices-why-ruby-isn-t-python-5726460 Why Ruby isn't Python]
+
For more Sequel tips, please see the [http://sequel.rubyforge.org/rdoc/files/doc/cheat_sheet_rdoc.html Sequel Cheat Sheet].
* [http://chargen.matasano.com/chargen/2009/8/30/ruby-for-pentesters-blackhat-09.html Ruby for Pentesters] [http://www.blackhat.com/presentations/bh-usa-09/TRACY/BHUSA09-Tracy-RubyPentesters-PAPER.pdf [paper]] [http://www.blackhat.com/presentations/bh-usa-09/TRACY/BHUSA09-Tracy-RubyPentesters-SLIDES.pdf [slides]]
+
{{programming}}
* [http://dontstuffbeansupyournose.com/2011/04/27/greyhat-ruby-source-boston/ Greyhat Ruby]
+
{{social}}

Latest revision as of 21:34, 14 October 2012

Ruby is an interpreted language, dynamically, reflective, semi-Functional and Object Orientated scripting language written in C. Ruby is said to be semi-Functional because it supports higher-order functions (aka lambdas) and closures (aka blocks). Ruby was created by Yukihiro "Matz" Matsumoto and was first released in 1995.

Matz's goal was to combine powerful features from various other programming languages, to create a programming language maximized for developer happiness; as opposed to computational efficiency. Ruby's Object Model mirrors that of Smalltalk, the syntax shares some similarities with Bash, Perl, Python, and the scoping rules for closures were taken from LISP.

Special thanks to Postmodern and Ohdazed for their contributions to this article.

Basics

Development Environment

  • Installation
  • Gems

Interactive Ruby Console

IRB, or the Interactive Ruby Console, comes bundled with Ruby and allows you to interactively run code right from your command line. IRB can be invoked from your terminal simply by typing 'irb'.

» irb --help Usage: irb.rb [options] [programfile] [arguments]

 -f		    Suppress read of ~/.irbrc 
 -m		    Bc mode (load mathn, fraction or matrix are available)
 -d                Set $DEBUG to true (same as `ruby -d')
 -r load-module    Same as `ruby -r'
 -I path           Specify $LOAD_PATH directory
 --inspect	    Use `inspect' for output (default except for bc mode)
 --noinspect	    Don't use inspect for output
 --readline	    Use Readline extension module
 --noreadline	    Don't use Readline extension module
 --prompt prompt-mode
 --prompt-mode prompt-mode

Switch prompt mode. Pre-defined prompt modes are `default', `simple', `xmp' and `inf-ruby'

 --inf-ruby-mode   Use prompt appropriate for inf-ruby-mode on emacs. 

Suppresses --readline.

 --simple-prompt   Simple prompt mode
 --noprompt	    No prompt mode
 --tracer	    Display trace for each execution of commands.
 --back-trace-limit n

Display backtrace top n and tail n. The default value is 16.

 --irb_debug n	    Set internal debug level to n (not for popular use)
 -v, --version	    Print the version of irb
$ irb
irb(main):001:0>puts 'woot'
woot
=> nil
irb(main):002:0>

Running irb --simple-prompt will provide you with a more basic looking Ruby shell.

$ irb --simple-prompt
>> puts 'woot'
woot
=> nil

You can use either 'exit', 'quit', or 'irb_exit' to close IRB and return to your terminal.

$ irb --simple-prompt
>> exit
$ # back in our terminal :D

RVM

RVM is a handy utility that can be used to manage multiple Ruby version installations on the same operating system. It allows you to run multiple interpreters and gemsets with a simple way to switch between them.

https://rvm.io/

Pry

Pry is a Ruby gem that provides an alterative to IRB (Interactive Ruby Console) with additional functionality to dig down into Ruby code while you are coding. You can view the source-code of any Ruby method from within the interpreter. It also provides some cool extras like Gist integration, syntax highlighting, and command shell integration.

Pry Homepage: https://github.com/pry/pry/

Your first program

Code

#!/usr/bin/ruby
puts "Hello world\n"

Style

While Ruby is not whitespace sensitive, all Rubyists share a certain style:

  1. Indent code using two spaces.
  2. All code must be within 80 columns.
  3. Class/Module names must be capitialized and CamelCased.
  4. Constants must be UPPERCASED_AND_UNDERSCORED.
  5. Method/variable names must be in snake_case.

For a complete Ruby Style Guide, please see the GitHub Ruby Style Guide.

Explanation

Variables

Local

A local variable is a variable that can only be used within the block it was initialized in. It can be created by assigning an Object to a lowercase keyword.

 
foo = 'bar'
 

Global

Global variables can be accessed from anywhere within the entire program. They can be created by prefixing your variable the the $ symbol. Editting the assignment of a global variable will change the status of that variable globally and is generally avoided when writing Ruby scripts; use class-variables or constants instead.

 
$woot = 1337
 

Instance Variables

Instance variables begin with the '@' symbol. Accessing an uninitialzed instance will return the nil value.

 
>> @instance
=> nil
>> @instance = 'ohdae'
=> "ohdae"
 

Instance variables can also be defined at the Class/Module level:

 
>> module Settings
>>   @config = {:verbose => false}
>>   def self.config; @config; end
>> end
=> Settings
>> Settings.config
=> {:verbose => false}
 

Class Variables

Class variables are shared by all methods within a Class or Module. These are created by using two '@' symbols at the beginning of your variable. Trying to initialize a class variable outside of a class will throw an error.

 
>> @@classvar
NameError: uninitialized class variable @@classvar in Object
	from (irb):5
	from :0
>> class Blackhat
>>   @@classvar = 'ohhai'
>>   def self.classvar; @@classvar; end
>> end
=> Blackhat
>> Blackhat.classvar
=> "ohhai"
 

Predefined Variables

Certain variables are pre-defined into Ruby. The values of these variables cannot be changed.

  • self: Represents the current scope. Similar to this from Java.
  • nil: The null object.
  • true: Boolean true.
  • false: Boolean false.

Data Types

Boolean Values

Ruby defines two boolean values, true and false:

 
>> 1 == 1
=> true
>> 1 == 2
=> false
 

Integers

Ruby also provides Integer literals:

 
>> 10
=> 10
>> 010 # octal
=> 8
>> 0x0a # hexadecimal
=> 10
>> 1_000_000 # short-hand for big values
=> 1000000
 

In Ruby, Integers are also Objects, which you can call methods on:

 
>> 0x42.chr
=> "A"
 

Floats

Ruby also provides floating point decimal literals:

 
>> 1.5
=> 1.5
>> 1.5e10
=> 15000000000.0
 

Floats are also Objects:

 
>> 1.5.round
=> 2
 

Strings

Ruby supports String literals as well.

 
>> "hello world"
=> "hello world"
>> 'hello\nworld'
=> "hello\\nworld"
>> "2 + 2 = #{2 + 2}" # String embedding
=> "2 + 2 = 4"
>> %{one
two
three}
=> "one\ntwo\nthree"
 

Strings are also Objects in Ruby:

 
>> "hello".reverse
=> "olleh"
 

Symbols

Symbols are like Strings, but used for keywords or identifiers:

 
>> :verbose
=> :verbose
>> :verbose == 'verbose'
=> false
>> :verbose == :verbose
=> true
 

Regular Expressions

Ruby supports inline Regular Expressions, or Regexps. Regular Expressions can be used to match Strings:

 
>> "1-555-3333" =~ /(\d-)?\d{3}-\d{4}/
=> 0
>> match = "Please call 1-555-3333".match(/(\d-)?\d{3}-\d{4}/)
=> #<MatchData "1-555-3333" 1:"1-">
>> match[0]
=> "1-555-3333"
 

Regexps can also be used to rewrite Strings:

 
>> "hello world".gsub(/e/,'3').gsub(/o/,'0')
=> "h3ll0 w0rld"
 

Arrays

An Array is a group of objects, very similar to lists in Python. The items or objects inside an array are indexed on a non-negative zero-index. The objects inside of a Ruby array can be any mixture of variables. Creating an array can be done in a few different ways. You do not need to specifically declare your variable as an array during initialization, for example if you give Ruby a list of comma separated values inside brackets, Ruby will recgonize this as an array and use it as such from that point forward.

 
>> my_array = []
=> []
>> array_three = ["item", 5, foo, "Item2", "Strings can go here too"]
=> ["item", 5, "bar", "Item2", "Strings can go here too"]
>> array_three[0]
=> "item"
>> array_three[1]
=> 5
>> array_with_default = Array.new(1)
=> []
>> array_with_default[0]
=> 1
>> filled_array = Array.new(5) { 0 }
=> [0, 0, 0, 0, 0]
 

You will notice the item 'foo' is printed as "bar" because we defined this earlier in this page.

Hashes or Associative Arrays

Ruby Hashes are similar to Arrays, except they require two objects for every item in the group. One of these objects is the 'key' and the other is the 'value'. This is very useful when you want to index items by some other than the array's zero-index. A hash also uses braces, instead of the brackets an array uses.

 
new_hash = {
  :username  => 'admin',
  :password  => 'letmein123',
  :hostname  => 'blackhatacademy.org',
  :service   => 'ssh'
  :port      =>  22
}
 

You can use the key inside of brackets to return the value for that object.

 
>> new_hash[:username]
=> 'admin'
 

Iterate through a hash, returning each key matched with it's value

 
>> new_hash.each do |k, v|
>>   puts "key: #{k}"
>>   puts "value: #{v}"
>> end
key: port
value: 22
key: hostname
value: blackhatacademy.org
key: service
value: ssh
key: username
value: admin
key: password
value: letmein123
=> {:port=>22, :hostname=>"blackhatacademy.org", :service=>"ssh", :username=>"admin", :password=>"letmein123"}
 

Hashes can also have default values:

 
>> counter = Hash.new(0)
=> {}
>> counter[:foo] += 1
=> 1
>> counter[:bar] += 2
=> 2
>> counter
=> {:foo=>1, :bar=>2}
 
>> require 'digest/md5'
=> true
>> md5s = Hash.new { |hash,key| hash[key] = Digest::MD5.hexdigest(key) }
=> {}
>> md5s['foo']
=> "acbd18db4cc2f85cedef654fccc4a4d8"
>> md5s['bar']
=> "37b51d194a7513e45b56f6524f2d51f2"
>> md5s
=> {"foo"=>"acbd18db4cc2f85cedef654fccc4a4d8", "bar"=>"37b51d194a7513e45b56f6524f2d51f2"}
 

Casting

Ruby is a dynamically typed language, so it doesn't have Static Types or Type-Casting. Instead it has methods which convert an Object into another format:

  • to_i: Converts an Object to an Integer.
  • to_f: Converts an Object to a Float.
  • to_s: Converts an Object to a String.
  • to_sym: Converts an Object to a Symbol.
  • to_a: Converts an Object to an Array.
  • to_set: Converts an Object to a Set.

Ruby also provides top-level methods for coercing an Object into another type:

 
>> Integer(1.5)
=> 1
>> Float(1)
=> 1.0
>> String(1.5)
=> "1.5"
>> Array(1)
=> [1]
>> Array(nil)
=> []
 

Operators

Boolean

Ruby supports all the usual ANSI C boolean operators:

 
>> true && false # AND
=> false
>> true || false # OR
=> true
>> true ^ true # XOR
=> false
>> !true # NOT
=> false
 

The &&, ||, ! operators can also be used with non-Boolean values. In Ruby, everything is treated as true, except for nil. As a result of this, you can use the ||= operator to lazily initialize variables:

 
module Settings
 
  def self.path
    @path ||= File.join(ENV['HOME'],'.foorc')
  end
 
end
 

Ternary Operator

Ruby supports the ternary operator, just like ANSI C:

 
number >= 0 ? :integer : :negative
 

Bitwise Manipulations

Main article: Bitwise math

Ruby supports all of the common ANSI C bit-wise operators:

 
>> 0xff & 0x02 # AND
=> 2
>> 0x02 | 0x1  # OR
=> 3
>> 0x02 ^ 0x3  # XOR
=> 1
>> ~0x0        # inverse
=> -1
>> 0x1 << 2    # left-shift
=> 4
>> 0x3 >> 1    # right-shift
=> 1
 

Statements

If

Like other scripting languages, Ruby supports if statements:

 
if x > 10
  puts 'greater than 10'
elsif x == 10
  puts 'equal to 10'
else
  puts 'less than 10'
end
 

if statements can also be written as one-liners:

 
puts 'x is a negative number' if x < 0
 

Ruby also provides an unless statement, which is equivalent to if !expression.

Case

Begin

Rescue

Ensure

Loops

For

Ruby supports for loops like any other language:

 
>> for i in (1..10)
>>   puts i
>> end
2
3
4
5
6
7
8
9
10
 

Generally, you never need to use for loops, due to Ruby's excellent support for Enumerators.

While

Ruby also supports traditional while loops:

 
>> queue = [1,2,3,4]
=> [1, 2, 3, 4]
>> while (i = queue.shift)
>>   puts i
>> end
1
2
3
4
 

Until

The until loop is a short-hand for saying while !expression:

 
>> queue = [1,2,3,4]
=> [1, 2, 3, 4]
>> until queue.empty?
>>   puts queue.shift
>> end
1
2
3
4
 

Enumerators

Ruby has superb support for Enumerators, or Iterators.

 
>> (1..5).each { |i| puts i }
1
2
3
4
5
=> 1..5
>> (1..5).first(2)                   # get the first two integers
=> [1, 2]
>> (1..5).any? { |i| i % 2 == 0 }    # are any even integers?
=> true
>> (1..5).all? { |i| i < 10 }        # are all integers less than 10?
=> true
>> (1..5).select { |i| i % 2 == 0 }  # select only even integers
=> [2, 4]
>> (1..5).map { |i| i * 2 }          # multiply every integer by two
=> [2, 4, 6, 8, 10]
 

These methods are defined by including the Enumerable module, and defining an each which enumerates over the elements of the Object:

 
>> class PasswordBruter
>>   include Enumerable
>>   def initialize(start_word)
>>     @start_word = start_word
>>     @end_word   = ('x' * start_word.length)
>>   end
>>   def each
>>     (@start_word..@end_word).each { |word| yield word }
>>   end
>> end
=> PasswordBruter
>> PasswordBruter.new("hello").each { |word| puts word }
hello
hellp
hellq
hellr
hells
hellt
hellu
hellv
hellw
hellx
....
 

Global Methods

defined?

Checks if a Class, Module or Constant is defined:

 
if defined?(RUBY_ENGINE)
  puts "Running on #{RUBY_ENGINE}"
end
 

send

Allows you to call arbitrary methods:

 
obj.send(method_name)
 

throw / catch

throw / catch: Throw and Catch allows one to jump out of a scope. This is similar to long jmp in Assembly:

 
def callback
  catch(:abort, :success) do
    puts 'yielding ...'
    yield
    puts 'completed!'
  end
end
 
>> callback { puts 'in the callback' }
yielding ...
in the callback
completed!
=> :success
>> callback { puts 'aborting!'; throw :abort, :failed }
=> :failed

raise

Raises an exception:

 
>> raise("error!")
RuntimeError: error!
	from (irb):38
>> raise(ArgumentError,"invalid argument")
ArgumentError: invalid argument
	from (irb):39
 

User Input

STDIN / STDOUT / STDERR

Ruby provides the STDIN, STDOUT and STDERR IO constants. You can use these constants to read-input or print output.

 
STDOUT.print "Password: "
 
password = STDIN.readline
 
if password.length < 6
  STDERR.puts "Password was too short!"
  exit -1
else
  puts "You entered: #{password}"
end
 

As you've probably guess, top-level IO methods, such as puts and readline, simply call to STDOUT or STDIN.

Ruby also provides the $stdin, $stdout, $stderr global variables, which allows you to hook/redirect all input/output. It's generally a good idea to use these global variables, instead of the constants.

Command-line Arguments

All command-line arguments are exposed via the ARGV constant.

 
#!/usr/bin/env ruby
puts "You passed the following arguments:"
ARGV.each { |arg| puts "  #{arg}" }
 

Ruby also provides an ARGF which is the File for the first file-argument:

 
#!/usr/bin/env ruby
 
unless ARGV[0]
  $stderr.puts "usage: #{$0} FILE"
  exit -1
end
 
ARGF.each_line do |line|
  # ...
end
 

If you need to parse command-line options, use the built-in OptionParser library.

Environment Variables

You can access and set Environment Variables via the ENV Hash:

 
>> ENV['HOME']
=> "/home/blackhatacademy"
 

User-defined

Methods

A simple hello world method:

 
 
def hello_world
  puts "Hello, World!"
end
 

When calling a method that takes an argument, the parenthesis around the argument are optional.

 
def hello(name)
  puts "Hello, #{name}!"
end
 
>> hello('ohdae')
Hello, ohdae!
=> nil
>> hello 'ohdae'
Hello, ohdae!
=> nil
 

Methods with default arguments:

 
def hello(name='ohdae')
  puts "Hello, #{name}!"
end
 
>> hello
Hello, ohdae!
=> nil
>> hello 'world'
Hello, world!
=> nil
 


Prematurely returning from a method:

 
def add(arg1, arg2) 
  return nil unless arg1
  return nil unless arg2
 
  arg1.to_i + arg2.to_i
end

Note, that we don't have to specify a return on the last line of our add method. This is because in Ruby, every statement has a return value, and the last-statement of a method is it's default return value.

Classes

Classes have names which must start in capital letters.

 
class MyClass
 
end
 

Classes can also inherit from other Classes:

 
class MyOtherClass < MyClass
 
end
 

In Ruby, the constructor method is called initialize:

 
class MyClass
  def initialize
    puts "Hello\n"
  end
end
 

Reader/writer methods for variables can also be defined within the class:

 
class MyClass
 
  # defines a foo method
  attr_reader :foo
 
  # defines a foo= method
  attr_writer :bar
 
  # defines foo and foo= methods
  attr_accessor :baz
 
  def initialize(foo,bar,baz)
    @foo, @bar, @baz = foo, bar, baz
  end
end
 

Modules

Modules are a way to group methods together, which can be included into multiple Classes. Modules allow you to compartmentalize common behaviours.

 
module HasName
  attr_accessor :name
 
  def initialize(name)
    @name = name
  end
 
  def named?(other_name)
    @name == other_name
  end
 
  def to_s
    @name.to_s
  end
 
end
 
class Person
 
  include HasName
 
end
 
class Computer
 
  include HasName
 
  def initialize(ip,name)
    @ip = ip
 
    super(name)
  end
 
end
 

Helpful Libraries

Ruby's stdlib provides many useful libraries.

Struct

Struct allows one to easily create Classes with specific attributes:

 
class Point < Struct.new(:x, :y)
end
 
>> p1 = Point.new(10, 20)
=> #<struct Point x=10, y=20>
>> p1.x
=> 10
>> p1.x += 20
=> 30

OpenStruct

OpenStruct is like Struct, but allows for arbitrary attributes:

 
>> require 'ostruct'
=> true
>> config = OpenStruct.new
=> #<OpenStruct>
>> config.x = 10
=> 10
>> config.name = 'foo'
=> "foo"
>> config.bla
=> nil
 

Set

Set is like an Array, but does not allow duplicates:

 
>> require 'set'
=> true
>> s = Set[]
=> #<Set: {}>
>> s << 1
>> s << 2
>> s << 2
>> s << 3
=> #<Set: {1, 2, 3}>
 

Base64

 
>> require 'base64'
=> true
>> Base64.encode64("hello")
=> "aGVsbG8=\n"
>> Base64.decode64("c2VjcmV0\n")
=> "secret"
 

Digest

The Digest module, provides classes for computing Cryptographic Hashes, such as MD5 and SHA256:

 
>> require 'digest/md5'
=> true
>> Digest::MD5.hexdigest("hello")
=> "5d41402abc4b2a76b9719d911017c592"
>> require 'digest/sha2'
=> true
>> Digest::SHA256.file('linux.iso')
=> "5a7eb8f97a196583530812132ef98fe9"
 

JSON

Ruby also provides a JSON serialization and parsing library:

 
>> require 'json'
=> true
>> JSON.parse("[1,2]")
=> [1, 2]
>> {1 => 2, 2 => 3}.to_json
=> "{\"1\":2,\"2\":3}"
 

Queue

Sockets

Simple TCP server:

 
require 'socket'
 
server = TCPServer.new 4444          # Binds to TCP port 4444
 
loop do                              # Starts a loop to wait for connection
  client = server.accept             # Receive and accept client connection
  client.puts "Hack The Planet!"     # Send data to client
  client.close
end
 

Simple TCP client:

 
require 'socket'
 
client = TCPSocket.new 'localhost', 4444      # Open TCP connection to localhost on port 4444
 
while line = client.gets                      # Read input from the socket connection
  puts line                                   # Prints the input we captured with s.gets
end                                      
 
client.close                                  # Closes the socket
 

URI

The URI library handles parsing and crafting of URIs:

 
>> require 'uri'
=> true
>> uri = URI("http://www.blackhatlibrary.net/index.php?title=Ruby&action=edit&section=42")
=> #<URI::HTTP:0x000000010e2080 URL:http://www.blackhatlibrary.net/index.php?title=Ruby&action=edit&section=42>
>> uri.host
=> "www.blackhatlibrary.net"
>> uri.port
=> 80
>> uri.query
=> "title=Ruby&action=edit&section=42"
 

Net::HTTP

open-uri

open-uri allows one to open URLs as temporary files:

 
>> require 'open-uri'
=> true
>> page = open(URI("http://www.blackhatlibrary.net/"))
=> #<File:/tmp/open-uri20120812-2361-143dlvc>
 

Gems

Gems are packaged Ruby libraries and scripts. Anyone can create their own gem and publish it to https://rubygems.org.

Gems are installed using the gem install:

$ gem install foo-bar

Once installed, you can require the gem:

require 'foo/bar'

Nokogiri

Nokogiri is a fast XML/HTML parser built ontop of libxml.

Installing on Debian / Ubuntu:

$ sudo apt-get install libxml2-dev libxslt1-dev
$ gem install nokogiri

Installing on RedHat / Fedora:

$ sudo yum install libxml2-devel libxslt-devel
$ gem install nokogiri
 
require 'nokogiri'
require 'open-uri'
 
doc = Nokogiri::HTML(open("http://www.reddit.com/"))
 
doc.search("div.entry a.title").each do |link|
  puts link.attributes['href']
end
 

Sequel

Sequel is a low-level SQL library for Ruby. It allows you to query tables and insert data, all without having to write raw SQL. Sequel supports SQLite3, MySQL, PostgreSQL, Oracle, etc.

Installing on Debian / Ubuntu:

$ sudo apt-get install libsqlite3-dev
$ gem install sqlite3-ruby sequel

Installing on RedHat / Fedora:

$ sudo yum install sqlite-devel
$ gem install sqlite3-ruby sequel
 
require 'sequel'
 
DB = Sequel.sqlite('file.sqlite3')
DB.create_table(:mytable) do
  integer: id
  varchar: name, :length => 256
end
 
DB[:mytable].insert(1, "foo")
DB[:mytable].insert(2, "bar")
DB[:mytable].where(:name => 'bar')
 

For more Sequel tips, please see the Sequel Cheat Sheet.

Ruby is part of a series on programming.
<center>
</center>