Ruby
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, 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.
Contents
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.
<pre> » 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.
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" |
Explanation
Variables and Data Types
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.
Boolean
Ruby defines two boolean values, true and false:
>> 1 == 1 => true >> 1 == 2 => false
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' 'portnum' => 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: portnum value: 22 key: hostname value: blackhatacademy.org key: service value: ssh key: username value: admin key: password value: letmein123 => {"portnum"=>22, "hostname"=>"blackhatacademy.org", "service"=>"ssh", "username"=>"admin", "password"=>"letmein123"}
References and Pointers
Casting
.to_i .to_s
Boolean Logic
Operators
Statements
Helper natives
Bitwise Manipulations
Loops
While
Until
For
Iterators
User Input
CGI & Eruby
Eruby has the same functionality as ruby with the added advantage of short tags from PHP. For example:
<html> <head> <title>Test</title> </head> <body> <% puts "Hello<br>" %> </body> </html> |
Command-line Options
STDIN / Standard Input
User-defined
Functions
simple hello world function
def hello_world puts 'Hello, World!' end |
When calling a function that takes an argument, the parenthesis around the argument is optional.
def hello(name) puts 'Hello, #{name}!" end hello('ohdae') => Hello, ohdae! hello 'ohdae' => Hello, ohdae! |
function with default arguments
def hello(name='ohdae') puts 'Hello, #{name}!" end hello => Hello, ohdae! hello 'world' => Hello, world! |
- Return values
def add(arg1, arg2) return nil unless defined? arg1 return nil unless defined? arg2 total = arg1.to_i + arg2.to_i return total end |
Objects
In ruby, class objects have names which must start in capital letters.
class MyClass end |
The constructor function is called initialize:
class MyClass def initialize() puts "Hello\n" end end |
Helpful Libraries
USqlite
require 'sqlite' class Usqlite attr_accessor :link, :config, :a_rows, :rows, :result, :data def initialize(config, *args) return nil unless defined? config @config = config @link = SQLite::Database.new(@config["sqlitefile"]) or exit("cannot open sqlite database") end def queryItem(query) return @link.get_first_value(query) end def queryRow(query) @link.results_as_hash = true @link.execute(query) do |row| @data = row return row end end def sqlQuery(query) @result = @link.query(query) end def sqlFetch() @link.results_as_hash = true return @data if (@data = @results.next) end def sqlInsert(query) @a_rows = 0 @link.query(query) do |result| @a_rows++ result.next end end end |
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 |