Ruby is a general purpose object oriented scripting language. It is inspired by PERL with Smalltalk like features. It is also functional, dynamic, imperative and reflective in all sense. It hase dynamic type system and contains automatic memory management.
Ruby was conceived on Feb 24, 1993 by Yukihiro Matsumoto, who wished to create a new language that balanced functional programming with imperative programming.
Reference
http://www.ruby-lang.org/en/
Learning a programming language
There are different ways to learn new programming/scripting language. Understand the basics and start with a simple project, keep building on the project until all areas you read are implemented in the project one way or the other. Or you can learn it by going over the basic syntax for the language. One you have the basic syntax, you can develop small modules that help you understand the basics, you inch forward until you become fairly comfortable with the language. Different people tend to have different approaches, I prefer the later approach. Reason, you hardly get dedicated time these days to pick up a project, and work end-to-end. It may take days, and some times weeks to read 200 page book. Given these limitations the second approach works better (for me). Why am I saying all this, because, I am going to run this page with the later approach, pick up bits and pieces of the language, connecting the dots is left to you. I'll throw some simple programs with some basic comments you can understand, follow and come up with your conventions. If you find any of the programs/solutions are not correct, feel free to shout, I'll try to attend to the as fast as possible.
Do I have the right tools with me
There are so many tools available for you to start programming Ruby - IronRuby, Eclipse (check Eclipse.org), NetBeans, JRuby plugin for Eclipse, and the list goes on
Let's get started
Ruby programs can be done with
Why should I always say HelloWorld first
Because you are asked to do so :) Let's follow the legacy without any more question
HelloWorld sample and Let's name it HelloWorld.rb
class HelloWorld
def initialize
puts("\nHello World\n")
end
#MAIN
helloWorld = HelloWorld.new
Let me take a minute to go over this simple program. In the above code we have created a simple class that contains nothing more than a 'initialize' (equal to a constructor in other languages like C++, C#, etc). There are no main methods in Ruby code. Anything that's coded outside a class is considered to be the main method
There are multiple ways to print text, variables. 'print' and 'puts' methods are nice ways to output text. If you want to print a value of a variable you can always do that by following the simple syntax of #{variable_name}
Well, I know what you are think. Alright, Alright, how do I accept some input form the user to print it back or manipulate on. That's where the 'gets' method come's in. Try this one out
def self.acceptNameAndSayHello
puts("\nYour name please: ")
name = STDIN.gets
puts("\n")
print %Q{Hello friend: #{name}}
puts("\n")
end
A simple class with definition
Let's do a little more now. What if I want to add more functions that accept parameters. Here's another sample of the same.
class HelloWorld
def initialize
puts("\nHello World\n")
end
def SayHello(name)
print %Q{Hello friend: #{name}}
puts("\n")
end
def self.SayHello
print %Q{Say hello}
puts("\n")
end
end
#MAIN
helloWorld = HelloWorld.new
HelloWorld.SayHello
helloWorld.SayHello("Krishnan")
Ruby by virtue of being a scripting language, does not have any data-types. That's right feel free to use variables of your choice. Variables are dynamically associated to their types based on how they are initialized. More on that later. For now, let's move on. One point you may want to remember is, Ruby is case sensitive. If you have initialized a variable "myName" and by mistake you use "MyName" else where in the code, consider you are out of luck. That won't work the way you wanted. So make sure what you type in
Remember the first function to execute in a class is 'initialize'.
Try out sample of code that returns a variety of data types - String, integer, floating value, boolean, etc
Basic conditions sample
Now that we have got some functions on the roll, how do I do some decision making - if, else if,switch statements at a glance
Simple If condition, and ternary operator
def SimpleIfCondition(name)
if(name != nil && name.length > 0) then
print "Name is not NIL!!!"
end
end
def SimpleIfElseIfCondition(designation)
if(designation == "Manager") then
puts("\nWelcome manager, hope you will have a nice day!")
elsif (designation == "Employee") then
puts("\nWelcome employee. Now shut-up and goto work!")
end
end
def SimpleTernaryOperation(name)
puts "\n Your name is #{name}"
isAdmin = (name == "Yukihiro Matsumoto") ? true : false
if(isAdmin) then
puts "\nWelcome administrator!"
else
puts "\nNot an administrator"
end
end
Switch case condition usage
def SimpleCaseCondition
print "\nEnter day today: "
day = STDIN.gets
day.chomp!
case day
when 1:
print "Sunday"
when 2:
print "Monday"
when 3:
print "Tuesday"
when 4:
print "Wednesday"
when 5:
print "Thursday"
when 6:
print "Friday"
else
print "Saturday"
end
end
end
Picking up a scripting language is pretty easy in early days and it can't get more simple than this. Let's keep rolling and move on to do some loops in Ruby
Basic loops sample
Loops help us to execute a single/set of statements multiple times or until a condition is satisfied. Ruby feeds developers with a lot of choices when it comes to loops, use them judiciously based on your needs - Until, while, for, Times, upto, downto and loop are the choices, example below may help you understand these easily
class SimpleLoopDemonstration
#until loop
def SimpleUntilLoop
x = 1
until x >= 10 do
puts x
x += 1
end
end
# while loop
def SimpleWhileLoop
x = 1
while x <= 10 do puts x x += 1 end end # for loop def SimpleForLoop x = 1 for x in 1..5 puts x end end # time's loop def TimesLoop 10.times { x PrintText(x) } end def SimpleUpTo PrintText("Simple Up To") 1.upto(10) { x PrintText(x) } end def SimpleDownTo PrintText("Simple Down To") 10.downto(1) { x PrintText(x) } end def simpleLoop x = 1 PrintText("Simple Loop") loop do x += 1 if x == 3 then break elsif x == 5 then next else PrintText(x) end end end def PrintText(someText) puts(someText) end end # MAIN part of the program puts "Hello World" simpleLoop = SimpleLoopDemonstration.new simpleLoop.SimpleWhileLoop puts "Until loop" simpleLoop.SimpleUntilLoop puts "for loop" simpleLoop.SimpleForLoop puts "10 times loop" simpleLoop.TimesLoop simpleLoop.SimpleUpTo simpleLoop.SimpleDownTo simpleLoop.simpleLoop
Now that we know the basic conditions and iterations, you can try different mathematical operations to get more comfortable in each of them
Here are some sample on string manipulation
class SimpleStringOperations
def initialize
@myText = "simple string manipulations"
end
def createString(str)
@myText = str
end
def concatenateText(attachText)
newText = @myText + attachText
return newText
end
def concatenateNumericValue(numericVal)
newText = @myText + numericVal.to_s
return newText
end
def removeLastChar
newText = @myText.chop
return newText
end
def findLength
return @myText.length
end
def reverseText
return @myText.reverse
end
def changeCase(toUpperCase)
return (toUpperCase == true) ? @myText.upcase : @myText.downcase
end
def self.printText(message)
print %Q{#{message}}
puts("\n")
end
def getText
return @myText
end
end
#MAIN part
stringOperations = SimpleStringOperations.new
stringOperations.createString("I love programming Ruby")
SimpleStringOperations.printText(stringOperations.getText)
newText = stringOperations.concatenateNumericValue(2.1)
SimpleStringOperations.printText(newText)
SimpleStringOperations.printText("Length of text is :" + stringOperations.findLength.to_s)
SimpleStringOperations.printText(stringOperations.reverseText)
SimpleStringOperations.printText(stringOperations.changeCase(true))
SimpleStringOperations.printText(stringOperations.changeCase(false))
SimpleStringOperations.printText(stringOperations.removeLastChar)
Want help on the function definitions, here's how you can get them
Simple mathematical operations
Integer and float point functions are used the same way we used string manipulation functions on string variables. Here are some functions that may come handy - abs, ceil, coerce, mod, floor, remainder, etc. There is one additional function that surprised me - next, succ. These 2 functions does an increment operation (similar to ++ in C++, C#). Here's a one simple implementation that you may not have seen so for. Note the way '?' has been used in the sample. That's how BOOLEAN functions are tested in RUBY
def valueIsInteger(inValue)
(inValue.integer? == true) ? printMessage("variable IS integer") : printMessage("variable IS NOT integer")
end
Object Oriented programming
If not for OOP, we can as well go ahead and so everything in something like Shell, Python and Perl. By virtue of being a scripting languages, Ruby does not support all features of OOP.
Here are a few of them that may help
Encapsulation & Abstraction
So far in all of the samples you may have noticed the usage of functions. Have we seen access-specifiers yet. Nope. We have 3 of them - 'public', 'private', 'protected'. As the name implies, Public is meant for complete access, private is meant for internal access only and protected is restricted access in hierarchal structure. A simple sample is added here, you can experiment more on them when you get a bit
Simple inheritence
Ruby supports single inheritence, meaning you can derive from a singular class only (unlike C++). I have created a simple sample to explain inheritence. Example is self-explanatory, and will give you an easy understanding of how inheritence works in Ruby. You may want to attempt some code changes like change the access specifiers, add functions, properties to the class and see how the overall behavior is
class LogMe
def self.Print(message)
print %Q{#{message}}
puts("\n")
end
end
class Person
public
attr_accessor :firstName, :lastName, :gender
private
attr_accessor :dateOfBirth
public
def initialize
end
def initialize(inFirstName, inLastName, inGender, inDateOfBirth)
@firstName = inFirstName
@lastName = inLastName
@gender = inGender
@dateOfBirth = inDateOfBirth
end
def getName
return @firstName + " " + @lastName
end
def getAge
# calculate Age from date of birth
return Time.now - @dateOfBirth
end
def personDetails
LogMe.Print("Name: " + getName + ", Age: " + getAge.to_s)
end
end
class Employee < Person protected attr_accessor :empId, :designation, :salary, :type public def initialize(inFirstName, inLastName, inGender, inDateOfBirth, inEmpId, inDesignation, inSalary, inType) super(inFirstName, inLastName, inGender, inDateOfBirth) @empId = inEmpId @designation = inDesignation @salary = inSalary @empType = inType end def provideEmployeeDetails personDetails LogMe.Print("Employee Id: " + @empId.to_s + ", Designation: " + @designation + ", Type: " + @empType) end end #MAIN part #person = Person.new "Bob", "Fredunberg", "Male", Time.local(1971, 3, 4) #LogMe.Print("Name: " + person.getName) #LogMe.Print("First Name: " + person.firstName) #LogMe.Print("Age: " + person.getAge.to_s) employee = Employee.new("Bob", "Fredunberg", "Male", Time.local(1971, 3, 4), 1, "Scintist", 300000, "Permanent") employee.provideEmployeeDetails
Polymorphism
Class, instance and global variables
Arrays
Handling arrays in RUBY is one of the most easiest to do. We have an in-built generic class 'Array'. Use Array class to instantiate a new instance for your case and use the tons of in-built functions to manipulate it. I have provided a simple example of a 'Family' were in persons are added, searched for, updated and removed. Hope this explains how Arrays work at a higher level. There are more functions available for the class please go through the RUBY manual to make effective use of them
class SimpleArray
attr_accessor :family
def initialize()
@family = ["Sam", "Bob", "Fred", "Smith"]
end
def AddPerson(person)
memberCount = @family.length;
@family.push(person)
end
def RemovePerson(person)
memberIndex = GetMemberIndex(person)
if(memberIndex > -1) then
@family.delete_at(memberIndex)
end
end
def RemoveAllMembers
@family = []
end
private
def GetMemberIndex(familyMember)
memberCount = 0
@family.each do member
if(familyMember == member) then
return memberCount
end
memberCount += 1
end
return -1
end
public
def Listfamily
if(@family == nil @family.length <= 0) then print %Q{@family is NIL. Please load values into @family} else puts(@family) end end private def searchFor(person) return @family.include?(person) end public def SearchPerson(person) if(@family == nil @family.length <= 0) then print %Q{There are no members in the family to search for.} return end if(searchFor(person) == true) then print %Q{Found the person. He's part of this family} else print %Q{Sorry, he's not a member of this family} end end def ReplacePersonWith(oldPerson, newPerson) if(searchFor(oldPerson) == true) print %Q{Found person: #{oldPerson}} end memberIndex = GetMemberIndex(oldPerson) if(memberIndex > -1) then
@family[memberIndex] = newPerson
print %Q{Member replaced!!!}
end
end
end
# MAIN part of the code
myfamily = SimpleArray.new()
myfamily.AddPerson("Mari")
puts("\n")
myfamily.Listfamily
myfamily.SearchPerson("Peter")
myfamily.ReplacePersonWith("Mari", "Mary")
puts("\n")
myfamily.Listfamily
myfamily.RemovePerson("Mary")
puts("\n")
myfamily.Listfamily
Maps
Arrays provide sequential access to a collection, what is you want to have a random access, Maps are the best alternative. use 'Hash' class to achieve the same. Take a look at the following sample to understand how to use it. In my sample I store name for a website (as key) and the website (as value). You can think of something that will make you understand better, if this does not suffice
class SimpleMaps
attr_accessor :urls
def initialize
@urls = Hash.new
print %Q{Hash map initialized}
end
def AddUrl(key, value)
LOG("\nAdd a URL #{key} with #{value}")
@urls[key] = value
end
def ListMap
LOG("\n Map List")
@urls.keys.each do key
LOG("\nKey is #{key}")
end
end
def SearchForUrl(inkey)
LOG("\nSearch for URL: #{inkey}")
@urls.keys.each do key
if(key == inkey) then
LOG("\nFound the #{inkey}")
end
end
end
def SearchForValue(invalue)
# check for contains too
LOG("\nSearch for value: #{invalue}")
@urls.keys.each do key
if(@url[key] == invalue) then
LOG("\nFound the #{invalue}")
end
end
end
private
def FindKey(inkey)
@urls.keys.each do key
if(key == inkey) then
return true
end
end
return false
end
public
def RemoveUrl(key)
LOG("\nRemove URL #{key}")
if(FindKey(key) == true) then
@urls.delete(key)
end
end
private
def LOG(message)
print %Q{#{message}}
end
end
# MAIN section
maps = SimpleMaps.new
maps.AddUrl("IT news", "www.zdnet.com")
maps.ListMap
maps.SearchForUrl("IT news")
maps.RemoveUrl("IT news")
maps.ListMap
Simple Regular expressionsRegular expression are life-lines for string manipulations. Any programmer who wishes cut short his work time on string manipulations should posses expertise in regular expression. It's an exciting subject, aptitude of a developer is intensely tested when working on complex regular expressions. Here are some samples to start with but you may want to build on these.
class LogMe
def self.PrintMessage(message)
print %Q{#{message}}
puts("\n")
end
end
class SimpleRegularExpressions
def initialize
end
def textContainsWord(inText, searchWord)
return (inText =~ /#{searchWord}/) ? true : false
end
def textContainsAnyOfWords(inText, inWord1, inWord2, inWord3)
return (inText =~ /#{inWord1} #{inWord2} #{inWord3}/) ? true : false
end
def doesTextStartWith(forWord)
return ("This is a sample text" =~ /^#{forWord}/i) ? true : false
end
def doesTextEndWithWord(withWord)
return ("This is a sample text" =~ /#{withWord}$/)
end
def doesMatchCollectionCharacters
if("This is a zample text" =~ /(svjk)ample/i) then
return true
end
return false
end
def someMoreSamples
string1 = "Steve was here"
# folowing condition will match for Steve, here too
if(string1 =~ /e.*e/) then
LogMe.PrintMessage("Found matching text")
end
# what if I want to find occurrences and information on them
string1 = "I will drill for well"
if(string1 =~ /(w.ll)/) then
print "Matched on ", $2, "\n"
end
string1 = "My phone number is (508)-001-1234"
if(string1 =~ /.\d{3}.{2}\d{3}.\d{4}/) then
LogMe.PrintMessage "Found a phone number"
end
end
end
# MAIN section
inText = "This is a sample text for RUBY regular expression sample"
regExp = SimpleRegularExpressions.new
if(regExp.textContainsWord(inText, "sample")) then
LogMe.PrintMessage("Found text match")
else
LogMe.PrintMessage("Sorry, canot find text")
end
if(regExp.textContainsAnyOfWords(inText, "PERL", "Python", "iOS")) then
LogMe.PrintMessage("Ah. Looks like the text is on scripting language")
else
LogMe.PrintMessage("Sorry, does not contain any message on scripting languages")
end
if(regExp.doesTextStartWith("This") == true) then
LogMe.PrintMessage("Start's with \"This\"")
else
LogMe.PrintMessage("Does not start with \"This\"")
end
if(regExp.doesTextEndWithWord("samples text")) then
LogMe.PrintMessage("Does end with \"sample\"")
else
LogMe.PrintMessage("Does not end with \"sample\"")
end
if(regExp.doesMatchCollectionCharacters) then
LogMe.PrintMessage("matches collection characters")
else
LogMe.PrintMessage("Does not match collection characters")
end
regExp.someMoreSamples
Simple file operations
Now that we have seen many areas of RUBY, one last step is handling files. How do I read, write into a file. RUBY provides us with 'File' class that has a variety of methods to create, open, read, write, rename, delete a file. In addition, it also allows us to query the type of file, check to see if the given path refers to a file or a directory, check to see if the location is valid and a lot more. I have provided a basic example, please refer to RUBY documentation to know more about this Object
class SimpleFileOperations
public
attr_accessor :file
attr_accessor :fileName
def initialize
@file = File.new("/Users/Rick/Private/Information.txt")
@fileName = "/Users/Rick/Private/Information.txt"
end
def closeFile
if(!@file.closed?) then
@file.close
end
end
def IsFileReadable
File.readable?(@fileName) ? true : false
end
def IsFileWritable
return File.writable?(@fileName) ? true : false
end
def IsFileExecutable
return File.executable?(@fileName) ? true : false
end
def fileSize
if(File.zero?(@fileName)) then
return 0
end
return File.size(@fileName)
end
def fileType
return File.fType(@fileName)
end
def someMetaInformation
print %Q{File Created on: #{File.ctime(@fileName)} and last modified on: #{File.mtime(@fileName)} and last accessed on: #{File.atime(@fileName)}}
end
def readFile
puts("Read File - #{@fileName}\n")
@fileName="test.dmp"
begin
@file = File.open(@fileName)
#@file.each {line puts(line)}
while(line = @file.gets)
puts(line)
end
@file.close
rescue => err
puts "Exception: #{err}"
err
end
end
end
# MAIN section
puts("Hello world")
fileOperations = SimpleFileOperations.new
puts("File options - Read: #{fileOperations.IsFileReadable}, Write: #{fileOperations.IsFileWritable}, Execute: #{fileOperations.IsFileExecutable}")
puts("File Size: #{fileOperations.fileSize}")
#puts("Type: #{fileOperations.fileType}")
puts("Some meta information")
fileOperations.someMetaInformation
fileOperations.readFile
What we/you may want to do nextI'll add more posts on the following sections
- Have a sample for OOP - develop a utility application
- More samples on regular expression
- More examples on File based operations
- Polymorphism explanation
No comments:
Post a Comment