Citation preview
BASIC COMPUTER CODING: RUBY
BIBLIOTEX Digital Library
www.bibliotex.com
BASIC COMPUTER CODING: RUBY
BIBLIOTEX Digital Library
www.bibliotex.com email: [email protected]
e-book Edition 2019 ISBN: 978-1-98462-685-1 (e-book)
This book contains information obtained from highly regarded resources. Reprinted material sources are indicated. Copyright for individual articles remains with the authors as indicated and published under Creative Commons License. A Wide variety of references are listed. Reasonable efforts have been made to publish reliable data and views articulated in the chapters are those of the individual contributors, and not necessarily those of the editors or publishers. Editors or publishers are not responsible for the accuracy of the information in the published chapters or consequences of their use. The publisher assumes no responsibility for any damage or grievance to the persons or property arising out of the use of any materials, instructions, methods or thoughts in the book. The editors and the publisher have attempted to trace the copyright holders of all material reproduced in this publication and apologize to copyright holders if permission has not been obtained. If any copyright holder has not been acknowledged, please write to us so we may rectify.
Notice: Registered trademark of products or corporate names are used only for explanation and identification without intent of infringement.
© 2019 3G E-learning LLC
In Collaboration with 3G E-Learning LLC. Originally Published in printed book format by 3G E-Learning LLC with ISBN 978-1-98462-285-3
EDITORIAL BOARD Aleksandar Mratinković is born on May 5, 1988. in Arandjelovac, Serbia. He has graduated on Economic high school (2007), The College of Tourism in Belgrade (2013), and also has a master degree of Psychology (Faculty of Philosophy, University of Novi Sad). He has been engaged in different fields of psychology (Developmental Psychology, Clinical Psychology, Educational Psychology and Industrial Psychology) and has published several scientific works.
Dan Piestun (PhD) is currently a startup entrepreneur in Israel working on the interface of Agriculture and Biomedical Sciences and was formerly presidentCEO of the National Institute of Agricultural Research (INIA) in Uruguay. Dan is a widely published scientist who has received many honours during his career including being a two-time recipient of the Amit Golda Meir Prize from the Hebrew University of Jerusalem, his areas of expertise includes stem cell molecular biology, plant and animal genetics and bioinformatics. Dan’s passion for applied science and technological solutions did not stop him from pursuing a deep connection to the farmer, his family and nature. Among some of his interest and practices counts enjoying working as a beekeeper and onboard fishing. Felecia Killings is the Founder and CEO of LiyahAmore Publishing, a publishing company committed to providing technical and educational services and products to Christian Authors. She operates as the Senior Editor and Writer, the Senior Writing Coach, the Content Marketing Specialist, Editor-in-Chief to the company’s quarterly magazine, the Executive and Host of an international virtual network, and the Executive Director of the company’s online school for Authors. She is a former high-school English instructor and professional development professor. She possesses a Master of Arts degree in Education and a Bachelor’s degree in English and African American studies. Dr. Sandra El Hajj, Ph.D. in Health Sciences from Nova Southeastern University, Florida, USA is a health professional specialized in Preventive and Global Health. With her 12 years of education obtained from one of the most prominent universities in Beirut, in addition to two leading universities in the State of Florida (USA), Dr. Sandra made sure to incorporate interdisciplinary and multicultural approaches in her work. Her long years of studies helped her create her own miniature world of knowledge linking together the healthcare field with Medical Research, Statistics, Food Technology, Environmental & Occupational Health, Preventive Health and most noteworthy her precious last degree of Global Health. Till today, she is the first and only doctor specialized in Global Health in the Middle East area. Hazem Shawky Fouda has a PhD. in Agriculture Sciences, obtained his PhD. From the Faculty of Agriculture, Alexandria University in 2008, He is working in Cotton Arbitration & Testing General Organization (CATGO).
Fozia Parveen has a Dphil in Sustainable Water Engineering from the University of Oxford. Prior to this she has received MS in Environmental Sciences from National University of Science and Technology (NUST), Islamabad Pakistan and BS in Environmental Sciences from Fatima Jinnah Women University (FJWU), Rawalpindi.
Igor Krunic 2003-2007 in the School of Economics. After graduating in 2007, he went on to study at The College of Tourism, at the University of Belgrade where he got his bachelor degree in 2010. He was active as a third-year student representative in the student parliament.Then he went on the Faculty of science, at the University of Novi Sad where he successfully defended his master’s thesis in 2013. The crown of his study was the work titled Opportunities for development of cultural tourism in Cacak“. Later on, he became part of a multinational company where he got promoted to a deputy director of logistic. Nowadays he is a consultant and writer of academic subjects in the field of tourism. Dr. Jovan Pehcevski obtained his PhD in Computer Science from RMIT University in Melbourne, Australia in 2007. His research interests include big data, business intelligence and predictive analytics, data and information science, information retrieval, XML, web services and service-oriented architectures, and relational and NoSQL database systems. He has published over 30 journal and conference papers and he also serves as a journal and conference reviewer. He is currently working as a Dean and Associate Professor at European University in Skopje, Macedonia.
Dr. Tanjina Nur finished her PhD in Civil and Environmental Engineering in 2014 from University of Technology Sydney (UTS). Now she is working as Post-Doctoral Researcher in the Centre for Technology in Water and Wastewater (CTWW) and published about eight International journal papers with 80 citations. Her research interest is wastewater treatment technology using adsorption process.
Stephen obtained his PhD from the University of North Carolina at Charlotte in 2013 where his graduate research focused on cancer immunology and the tumor microenvironment. He received postdoctoral training in regenerative and translational medicine, specifically gastrointestinal tissue engineering, at the Wake Forest Institute of Regenerative Medicine. Currently, Stephen is an instructor for anatomy and physiology and biology at Forsyth Technical Community College.
Michelle holds a Masters of Business Administration from the University of Phoenix, with a concentration in Human Resources Management. She is a professional author and has had numerous articles published in the Henry County Times and has written and revised several employee handbooks for various YMCA organizations throughout the United States.
Table of Contents Preface
Chapter 1
Ruby Basics
xi
1
Learning Objectives ............................................................................. 1 Introduction.......................................................................................... 2 1.1 Concept of Ruby Basics ................................................................ 2 1.1.1 General concepts ..................................................................6 1.1.2 Numbers ................................................................................8 1.1.3 Strings ....................................................................................8 1.1.4 Arrays ...................................................................................10 1.1.5 Hashes ..................................................................................11 1.2 Rails Basics.................................................................................... 12 1.2.1 The Structure of a Rails app ..............................................14 1.2.2 Important Rails Commands..............................................16 1.2.3 ERB: Embedded Ruby .......................................................18 1.2.4 Editor tips ............................................................................19 1.3 The History of Ruby .................................................................... 20 1.3.1 Toddler Years ......................................................................20 1.3.2 The Rebellious Teenager....................................................22 1.3.3 The Future ...........................................................................24 Role Model.......................................................................................... 25 Summary............................................................................................. 27 Knowledge Check ............................................................................. 28 Review Questions .............................................................................. 29 References ........................................................................................... 30
Chapter 2
Working with Strings, Objects, and Variables
31
Learning Objectives ........................................................................... 31 Introduction........................................................................................ 32 2.1 Ruby - Strings ............................................................................... 33 2.1.1 Concatenation .....................................................................33 2.1.2 Case ......................................................................................34 2.1.3 Length ..................................................................................35
2.1.4 Strip ......................................................................................36 2.2 Objects and Methods................................................................... 36 2.2.1 Objects and Attributes .......................................................41 2.3 Variable In Ruby .......................................................................... 44 2.3.1 Local Variable......................................................................44 2.3.2 Instance Variables ...............................................................47 2.3.3 Class Variables ....................................................................49 2.3.4 Global Variables ..................................................................50 2.3.5 Ruby Constants...................................................................51 Case Study .......................................................................................... 55 Summary............................................................................................. 59 Knowledge Check ............................................................................. 60 Review Questions .............................................................................. 61 References ........................................................................................... 62
Chapter 3
Implementing Conditional Logic
65
Learning Objectives ........................................................................... 65 Introduction........................................................................................ 66 3.1 Conditional Statement ................................................................ 66 3.1.1 The if Statement ..................................................................66 3.1.2 The case Statement .............................................................71 3.1.3 The While Loop ..................................................................73 3.2 Comparison Operators ............................................................... 78 3.3 Assignment Operators ................................................................ 81 3.4 Logical Operators ........................................................................ 83 3.4.1 Logical and ..........................................................................83 3.4.2 Logical or .............................................................................84 3.4.3 Logical not ...........................................................................85 3.5 Ternary Operator ......................................................................... 89 Summary............................................................................................. 91 Knowledge Check ............................................................................. 92 Review Questions .............................................................................. 93 References ........................................................................................... 94
Chapter 4
Working with Loops
95
Learning Objectives ........................................................................... 95 Introduction........................................................................................ 96
4.1 A Simple Loop .............................................................................. 96 4.2 Controlling Loop Execution ....................................................... 97 4.3 While Loops.................................................................................. 99 4.4 Until Loops ................................................................................. 103 4.5 Do/While Loops ......................................................................... 104 4.6 For Loops .................................................................................... 105 4.7 Conditionals Within Loops ...................................................... 107 4.8 Iterators ....................................................................................... 109 4.9 Recursion .................................................................................... 110 4.10 Ruby Flip-Flop ......................................................................... 114 Case Study ........................................................................................ 115 Summary .......................................................................................... 116 Knowledge Check ........................................................................... 117 Review Questions ............................................................................ 118 References ......................................................................................... 120
Chapter 5
Working With Regular Expressions
121
Learning Objectives ......................................................................... 121 Introduction...................................................................................... 122 5.1 Mastering Ruby Regular Expressions .................................... 122 5.1.1 Regular-Expression Modifiers ........................................123 5.1.2 Search and Replace ..........................................................124 5.1.3 Regular-Expression Patterns ...........................................126 5.2 Digging Deeper .......................................................................... 129 5.2.1 Regular Expression Options ...........................................130 5.2.2 Deeper Patterns.................................................................132 5.2.3 Literal Characters .............................................................132 5.2.4 Character Classes .............................................................133 5.2.5 Special Character Classes ................................................137 5.2.6 Repetition Cases ...............................................................138 5.2.7 Grouping with Parentheses ............................................141 5.2.8 Alternatives .......................................................................143 5.2.9 Anchors ..............................................................................144 5.2.10 Pattern-Based Substitution ............................................145 5.2.11 Backslash Sequences in the Substitution.....................147 Summary........................................................................................... 150 Knowledge Check ........................................................................... 151
Review Questions ............................................................................ 152 References ......................................................................................... 153
Chapter 6
Ruby: Object-Oriented Programming
155
Learning Objectives ......................................................................... 155 Introduction...................................................................................... 156 6.1 Definition of Ruby Class........................................................... 156 6.1.1 Define Ruby Objects.........................................................157 6.1.2 The accessor & setter Methods .......................................159 6.1.3 The class Methods and Variables ...................................164 6.1.4 The to_s Method ...............................................................165 6.1.5 Access Control ..................................................................167 6.2 Class Inheritance........................................................................ 169 6.2.1 Methods Overriding ........................................................171 6.2.2 Operator Overloading .....................................................172 6.2.3 Freezing Objects ...............................................................173 6.2.4 Class Constants .................................................................175 6.2.5 Create Object Using Allocate ..........................................177 6.2.6 Class Information .............................................................178 Summary........................................................................................... 180 Knowledge Check ........................................................................... 181 Review Questions ............................................................................ 182 References ......................................................................................... 183
Chapter 7
Debugger
185
Learning Objectives ......................................................................... 185 Introduction...................................................................................... 186 7.1 Ruby – Debugger ....................................................................... 187 7.1.1 Usage Syntax .....................................................................187 7.1.2 Ruby Debugger Commands ...........................................188 7.2 The Logger .................................................................................. 191 7.2.1 What is the Logger? .........................................................191 7.2.2 Log Levels..........................................................................192 7.2.3 Sending Messages ............................................................192 7.2.4 Tagged Logging ................................................................194 7.2.5 Impact of Logs on Performance .....................................195 7.3 Debugging With The Bye Bug Gem ........................................ 196
7.3.1 Setup...................................................................................196 7.3.2 The Shell ............................................................................196 7.3.3 The Context .......................................................................200 7.3.4 Threads ..............................................................................202 7.3.5 Inspecting Variables .........................................................202 7.3.6 Step by Step .......................................................................205 7.3.7 Breakpoints........................................................................207 7.3.8 Catching Exceptions.........................................................209 7.3.9 Resuming Execution ........................................................209 7.3.10 Editing ..............................................................................209 7.3.11 Quitting ............................................................................209 7.3.12 Settings .............................................................................210 Summary .......................................................................................... 212 Knowledge Check ........................................................................... 214 Review Questions ............................................................................ 215 References ......................................................................................... 216
Index
217
Preface Ruby is a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write, since it allows its users to freely alter its parts. One of the goals of Ruby is to allow the simple and fast creation of web applications. The language itself satisfies this goal. Because of this, there is much less tedious work with this language than many other programming languages. In Ruby, everything is an object. Every bit of information and code can be given their own properties and actions. Object-oriented programming calls properties by the name instance variables and actions are known as methods. Ruby’s pure object-oriented approach is most commonly demonstrated by a bit of code which applies an action to a number. In the world of computer programming, there is an infinite amount of information to learn. This book covers certain topics that are beneficial to the beginner. Organization of the Book This book is systematically divided into seven chapters. This book is your guide to rapid, real-world software development with this unique and elegant language. The book will excite students on the capabilities of computer programming and inspire them to delve deeper into the computer science discipline. It will give you plenty of practice to commit basic Ruby syntax to long-term memory so you can focus on solving real-world problems and building real-world applications. Chapter 1 presents an introduction to Ruby Basics. It also explains the strings, arrays, hashes. You will take a look at the general structure of a Rails application and the important commands used in the terminal. Chapter 2 shows you how to work with Strings, Objects, and Variables. There are two kinds of objects: built-in objects and custom objects. Built-in objects are predefined objects that all programmers
can use. They are available with the core of the Ruby language or from various libraries. Custom objects are created by application programmers for their application domains. Chapter 3 begins with the conditional statement. It also explains sets and files used in Python. Comparison operators and assignment operators is also given. Additionally, it also explains the logical operators and ternary operator. Chapter 4 presents an exploration on working with loops in Ruby used to execute the same block of code a specified number of times. In this chapter, the loop statements supported by Ruby are also discussed. Chapter 5 is aimed to the ruby regular expressions that can be matched against a string. Regular expression literals may include an optional modifier to control various aspects of matching. Chapter 6 will take you through all the major functionalities related to Object Oriented Ruby. A class is used to specify the form of an object and it combines data representation and methods for manipulating that data into one neat package. The data and methods within a class are called members of the class. Chapter 7 discusses about the debugging process in software development whereby program analysts comb through computer code looking for “bugs” — the source of errors, flaws or security holes in the internal program instructions.
CHAPTER 1
RUBY BASICS “Ruby is simple in appearance, but is very complex inside, just like our human body ” ―Matz
Learning Objectives After studying this chapter, you will be able to: ■
Focus on concept of ruby basics
■
Explain the rails basics
■
Describe the history of ruby
Basic Computer Coding: Ruby
INTRODUCTION Ruby is a cross-platform interpreted language which has many features in common with other ‘scripting’ languages such as Perl and Python. However, its version of object orientation is more thorough than those languages and, in many respects, it has more in common with the great-granddaddy of ‘pure’ OOP languages, Smalltalk. The Ruby language was created by Yukihiro Matsumoto (commonly known as ‘Matz’) and it was first released in 1995.
1.1 CONCEPT OF RUBY BASICS Ruby is the programming language Ruby on Rails is written in. So most of the time you will be writing Ruby code. Therefore it is good to grasp the basics of Ruby. If you just want to play with Ruby, type irb into your console to start interactive ruby. There you can easily experiment with Ruby. To leave irb, type exit. This is just a very small selection of concepts. This is especially true later on when we talk about what Arrays, Strings etc. can do.
Everything is an Object Everything in Ruby is an Object. # This is a comment #=> Output will be shown like this #Everything is an Object of a Class 3.class #=> Fixnum 3.0.class #=> Float “Hello”.class #=> String ‘hi’.class #=> String # Special values are objects too nil.class #=> NilClass true.class #=> TrueClass
2
Ruby Basics
false.class #=> FalseClass Basic arithmetic Ruby uses the standard arithmetic operators: 1 + 1 #=> 2 10 * 2 #=> 20 35 / 5 #=> 7 10.0 / 4.0 #=> 2.5 4 % 3 #=> 1 #Modulus 2 ** 5
#=> 32 #Exponent
Arithmetic is just syntactic sugar for calling a method on Numeric objects. 1.+(3) #=> 4 10.* 5 #=> 50 The Integer class has some integer-related functions, while the Math module contains trigonometric and other functions. 2.even? #=> true 12.gcd(8) #=> 4 Equality and Comparisons #equality 1 == 1 #=> true 2 == 1 #=> false # Inequality 1 != 1 #=> false 2 != 1 #=> true !true #=> false !false #=> true #Logical Operators 3>2 && 2>1 #=> true 2>3 && 2>1 #=> false 2>3 || 2>1 #=> true 3
Arithmetic operators take numerical values (either literals or variables) as their operands and return a single numerical value.
Basic Computer Coding: Ruby
#In Ruby, you can also use words true and false #=> false true or false #=> true true and not false => true # apart from false itself, nil is the only other ‘false’ value !nil #=> true !false #=> true !1
#=> false
!0
#=> false
#comparisons 1 < 10 #=> true 1 > 10 #=> false 2 true 2 >= 2 #=> true Challenge What will the following code return? true and 0 && !nil and 3 > 2 (Note: don’t use such code in real programs!) Please sign in or sign up to submit answers. Alternatively, you can try out Learneroo before signing up. Variables x = 25 #=> 25 x #=> 25 4
Ruby Basics
# Note that assignment returns the value assigned # This means you can do multiple assignment: x = y = 10 #=> 10 x #=> 10 y #=> 10 # Variables can be dynamically assigned to different types thing = 5 #=> 5 thing = “hello” #=> “hello” thing = true #=> true # By convention, use snake_case for variable names snake_case = true # Use descriptive variable names path_to_project_root = ‘/good/name/’ Remember
path = ‘/bad/name/’ Challenge ab is considered powerful if (and only if) both of the following 2 conditions are met: 1. ab >= 2 * b2 2. ab >= (a*b)2 return true if ab is powerful and false otherwise. Please sign in or sign up to submit answers. Alternatively, you can try out Learneroo before signing up. 5
Interactive Ruby (IRb) provides a shell for experimentation. Within the IRb shell, you can immediately view expression results, line by line.
Basic Computer Coding: Ruby
1.1.1 General concepts Concept
Usage
Examples
Description
Comment
# Comment text
# This text is a comment
Ruby ignores everything that is marked as a comment. It does not try to execute it. Comments are just there for you as information. Comments are also commonly used to comment out code. That is when you don’t want some part of your code to execute but you don’t want to delete it just yet, because you are trying different things out.
some.ruby_code # A comment # some.ignored_ruby_ code
Variables
variable = some_ value
name = “Tobi” name # => “Tobi” sum = 18 + 5 sum # => 23
Console output
puts something
Call a method
object. method(arguments)
puts “Hello World” puts [1, 5, “mooo”]
string.length array.delete_at(2) string.gsub(“ae”, “ä”)
With a variable you tell Ruby that from now on you want to refer to that value by the name you gave it. So for the first example, from now on when you use name Ruby will know that you meant “Tobi”. Prints its argument to the console. Can be used in Rails apps to print something in the console where the server is running. Calling a method is also often referred to as sending a message in Ruby. Basically we are sending an object some kind of message and are waiting for its response. This message may have no arguments or multiple arguments, depending on the message. So we kindly ask the object to do something or give us some information. When you «call a method» or «send a message» something happens. In the first example we ask a String how long it is (how many characters it consists of). In the last example we substitute all occurrences of «ae” in the string with the German “ä”. Different kinds of objects (Strings, Numbers, Arrays...) understand different messages.
6
Ruby Basics Define a method
def name(parameter) # method body end
def greet(name) puts “Hi there “ + name end
Methods are basically reusable units of behavior. And you can define them yourself just like this. Methods are small and focused on implementing a specific behavior. Our example method is focused on greeting people. You could call it like this: greet(“Tobi”)
Equality
object == other
true == true # => true 3 == 4 # => false “Hello” == «Hello» # => true
With two equal signs you can check if two things are the same. If so, true will be returned; otherwise, the result will be false.
“Helo” == “Hello” # => false
Inequality
object != other
true != true # => false 3 != 4 # => true
Decisions with if
if condition # happens when true else # happens when false end
if input == password grant_access else deny_access end
Inequality is the inverse to equality, e.g. it results in true when two values are not the same and it results in false when they are the same. With if-clauses you can decide based upon a condition what to do. When the condition is considered true, then the code after it is executed. If it is considered false, the code after the «else» is executed. In the example, access is granted based upon the decision if a given input matches the password.
Constants
CONSTANT = some_value
PI = 3.1415926535 PI # => 3.1415926535 ADULT_AGE = 18 ADULT_AGE # => 18
7
Constants look like variables, just in UPCASE. Both hold values and give you a name to refer to those values. However while the value a variable holds may change or might be of an unknown value (if you save user input in a variable) constants are different. They have a known value that should never change. Think of it a bit like mathematical or physical constants. These don’t change, they always refer to the same value.
Basic Computer Coding: Ruby
1.1.2 Numbers Numbers are what you would expect them to be, normal numbers that you use to perform basic math operations. Concept
Usage
Examples
Description
normal Number
number_of_your_ choice
0
Numbers are natural for Ruby, you just have to enter them!
-11 42
Decimals
main.decimal
3.2 -5.0
Basic Math
n operator m
2 + 3 # => 5 5 - 7 # => -2 8 * 7 # => 56
You can achieve decimal numbers in Ruby simply by adding a point. In Ruby you can easily use basic math operations. In that sense you may use Ruby as a super-powered calculator.
84 / 4 # => 21 Comparison
n operator m
12 > 3 # => true 12 < 3 # => false 7 >= 7 # => true
Numbers may be compared to determine if a number is bigger or smaller than another number. When you have the age of a person saved in the age variable you can see if that person is considered an adult in Germany: age >= 18 # true or false
1.1.3 Strings Strings are used to hold textual information. They may contain single characters, words, sentences or a whole book. However you may just think of them as an ordered collection of characters.
8
Ruby Basics Concept
Usage
Examples
Description
Create
‘A string’
‘Hello World’
A string is created by putting quotation marks around a character sequence. A Ruby style guide recommends using single quotes for simple strings.
‘a’ ‘Just characters 129 _!$%^’ ‘’ Interpolation
“A string and an #{expression}”
“Email: #{user.email}” “The total is #{2 + 2}” “A simple string”
Length
string.length
“Hello”.length # => 5 “”.length # => 0
Concatenate
string + string2
“Hello “ + “reader” # => “Hello reader” “a” + “b” + “c” # => «abc”
Substitute
string.gsub(a_string, substitute)
“Hae”.gsub(“ae”, “ä”) # => “Hä” “Hae”.gsub(“b”, “ä”) # => “Hae”
You can combine a string with a variable or Ruby expression using double quotation marks. This is called “interpolation.” It is okay to use double quotation marks around a simple string, too. You can send a string a message, asking it how long it is and it will respond with the number of characters it consists of. You could use this to check if the desired password of a user exceeds the required minimum length. Notice how we add a comment to show the expected result. Concatenates two or more strings together and returns the result.
gsub stands for «globally substitute». It substitutes all occurrences of a_string within the string with substitute.
“Greenie”.gsub(“e”, “u”) # => “Gruuniu”
Access
string[position]
“Hello”[1] # => “e”
9
Access the character at the given position in the string. Be aware that the first position is actually position 0.
Basic Computer Coding: Ruby
1.1.4 Arrays An array is an ordered collection of items which is indexed by numbers. So an array contains multiple objects that are mostly related to each other. So what could you do? You could store a collection of the names of your favorite fruits and name it fruits. This is just a small selection of things an Array can do. Concept
Usage
Examples
Description
Create
[contents]
[]
Creates an Array, empty or with the specified contents.
[“Rails”, “fun”, 5] Number of elements
array.size
[].size # => 0 [1, 2, 3].size # => 3
Returns the number of elements in an Array.
[“foo”, “bar”].size # => 2 Access
array[position]
array = [“hi”, “foo”, “bar”] array[0] # => “hi” array[2] # => “bar”
As an Array is a collection of different elements, you often want to access a single element of the Array. Arrays are indexed by numbers so you can use a number to access an individual element. Be aware that the numbering actually starts with “0” so the first element actually is the 0th. And the last element of a three element array is element number 2.
Adding an element
array [“hi”, “foo”, “new”]
Assigning new Array Values works a lot like accessing them; use an equals sign to set a new value. Voila! You changed an element of the array! Weehuuuuu!
Delete at index
array.delete_at(i)
array = [0, 14, 55, 79] array.delete_ at(2) array # => [0, 14, 79]
Deletes the element of the array at the specified index. Remember that indexing starts at 0. If you specify an index larger than the number of elements in the array, nothing will happen.
10
Ruby Basics Iterating
array.each do |e| .. end
persons.each do |p| puts p.name end numbers.each do |n| n = n * 2 end
“Iterating” means doing something for each element of the array. Code placed between do and end determines what is done to each element in the array. The first example prints the name of every person in the array to the console. The second example simply doubles every number of a given array.
1.1.5 Hashes Hashes associate a key to some value. You may then retrieve the value based upon its key. This construct is called a dictionary in other languages, which is appropriate because you use the key to «look up» a value, as you would look up a definition for a word in a dictionary. Each key must be unique for a given hash but values can be repeated. Hashes can map from anything to anything! You can map from Strings to Numbers, Strings to Strings, Numbers to Booleans... and you can mix all of those! Although it is common that at least all the keys are of the same class. Symbols are especially common as keys. Symbols look like this: symbol. A symbol is a colon followed by some characters. You can think of them as special strings that stand for (symbolize) something! We often use symbols because Ruby runs faster when we use symbols instead of strings.
11
A string is called a special string if it does not contain a vowel i.e., (a,e,i,o,u) in the first three characters or last three characters
Basic Computer Coding: Ruby Concept
Usage
Examples
Description
Creating
{key => value}
{:hobby => «programming»}
You create a hash by surrounding the key-value pairs with curly braces. The arrow always goes from the key to the value depicting the meaning: “This key points to this value.”. Key-value pairs are then separated by commas.
Accessing
hash[key]
hash = {:key => “value”} hash[:key] # => “value” hash[foo] # => nil
Accessing an entry in a hash looks a lot like accessing it in an array. However with a hash the key can be anything, not just numbers. If you try to access a key that does not exist, the value nil is returned, which is Ruby’s way of saying “nothing”, because if it doesn’t recognize the key it can’t return a value for it.
Assigning
hash[key] = value
hash = {:a => “b”} hash[:key] = “value” hash # => {:a=>”b”, :key=>”value”}
Assigning values to a hash is similar to assigning values to an array. With a hash, the key can be a number or it can be a symbol, string, number... or anything, really!
Deleting
hash. delete(key)
hash = {:a => “b”, :b => 10} hash.delete(:a) hash # => {:b=>10}
You can delete a specified key from the hash, so that the key and its value can not be accessed.
{42 => “answer”, “score” => 100, :name => “Tobi”}
1.2 RAILS BASICS This is an introduction to the basics of Rails. We look at the general structure of a Rails application and the important commands used in 12
Ruby Basics
the terminal. If you do not have Rails installed yet, there is a well maintained guide by Daniel Kehoe on how to install Rails on different platforms. Running the ruby command launched the Ruby interpreter. The Ruby interpreter read the file you specified and evaluated its contents. It executed the line puts “Hello, World!” by calling the puts function. The string value of Hello, World! Was passed to the function. In this example, the string Hello, World! is also called an argument since it is a value that is passed to a method.
Currently much of the excitement surrounding Ruby can be attributed to a web development framework called Rails – popularly known as ‘Ruby on Rails’. While Rails is an impressive framework, it is not the be-all and end-all of Ruby. Indeed, if you decide to leap right into Rails development without first mastering Ruby, you may find that you end up with an application that you don’t even understand. While the Little Book of Ruby won’t cover the special features of Rails, it will give you the grounding you need to understand Rails code and write your own Rails applications.
Installing and Using Ruby with Ruby in Steel Ruby in Steel is a Windows-based IDE which comes with an all-in-one installer to install Ruby, Visual Studio, Ruby in Steel and various other optional packages including Rails.
13
In computer systems, a framework is often a layered structure indicating what kind of programs can or should be built and how they would interrelate. Some computer system frameworks also include actual programs, specify programming interfaces, or offer programming tools for using the frameworks.
Basic Computer Coding: Ruby
Installing Ruby Yourself If you are using some other IDE or editor, you will need to download the latest version A debugger is a computer program used of Ruby from www.ruby-lang.org. Be sure to by programmers to download the binaries. test and debug a target program.
Running Ruby Programs It is often useful to keep a Command window open in the source directory containing your Ruby program files. Assuming that the Ruby interpreter is correctly pathed on your system, you will then be able to run programs by entering ruby like this: ruby 1helloworld.rb If you are using Ruby In Steel you can run the programs in the interactive console by pressing CTRL+F5 or (in some editions) you may run them in the debugger by pressing F5.
1.2.1 The Structure of a Rails app Here is an overview of all the folders of a new Rails application, outlining the purpose of each folder, and describing the most important files. Name
Description
app
This folder contains your application. Therefore it is the most important folder in Ruby on Rails and it is worth digging into its subfolders. See the following rows.
app/assets
Assets basically are your front-end stuff. This folder contains images you use on your website, javascripts for all your fancy front-end interaction and stylesheets for all your CSS making your website absolutely beautiful.
app/ controllers
The controllers subdirectory contains the controllers, which handle the requests from the users. It is often responsible for a single resource type, such as places, users or attendees. Controllers also tie together the models and the views.
14
Ruby Basics app/helpers
Helpers are used to take care of logic that is needed in the views in order to keep the views clean of logic and reuse that logic in multiple views.
app/mailers
Functionality to send emails goes here.
app/models
The models subdirectory holds the classes that model the business logic of our application. It is concerned with the things our application is about. Often this is data, that is also saved in the database. Examples here are a Person, or a Place class with all their typical behaviour.
app/views
The views subdirectory contains the display templates that will be displayed to the user after a successful request. By default they are written in HTML with embedded ruby (.html.erb). The embedded ruby is used to insert data from the application. It is then converted to HTML and sent to the browser of the user. It has subdirectories for every resource of our application, e.g. places, persons. These subdirectories contain the associated view files. Files starting with an underscore (_) are called partials. Those are parts of a view which are reused in other views. A common example is _form.html.erbwhich contains the basic form for a given resource. It is used in the new and in the edit view since creating something and editing something looks pretty similar.
config
This directory contains the configuration files that your application will need, including your database configuration (in database.yml) and the particularly important routes.rb which decides how web requests are handled. The routes.rb file matches a given URL with the controller which will handle the request.
db
Contains a lot of database related files. Most importantly the migrations subdirectory, containing all your database migration files. Migrations set up your database structure, including the attributes of your models. With migrations you can add new attributes to existing models or create new models. So you could add the favorite_color attribute to your Person model so everyone can specify their favorite color.
doc
Contains the documentation you create for your application. Not too important when starting out.
lib
Short for library. Contains code you’ve developed that is used in your application and may be used elsewhere. For example, this might be code used to get specific information from Facebook.
log
See all the funny stuff that is written in the console where you started the Rails server? It is written to your development.log. Logs contain runtime information of your application. If an error happens, it will be recorded here.
public
Contains static files that do not contain Ruby code, such as error pages.
15
Basic Computer Coding: Ruby script
By default contains what is executed when you type in the rails command. Seldom of importance to beginners.
test
Contains the tests for your application. With tests you make sure that your application actually does what you think it does. This directory might also be called spec, if you are using the RSpec gem (an alternative testing framework).
vendor
A folder for software code provided by others (“libraries”). Most often, libraries are provided as ruby gems and installed using the Gemfile. If code is not available as a ruby gem then you should put it here. This might be the case for jQuery plugins. Probably won’t be used that often in the beginning.
Gemfile
A file that specifies a list of gems that are required to run your application. Rails itself is a gem you will find listed in the Gemfile. Ruby gems are self-contained packages of code, more generally called libraries that add functionality or features to your application. If you want to add a new gem to your application, add “gem gem_name” to your Gemfile, optionally specifying a version number. Save the file and then run bundle install to install the gem.
Gemfile.lock This file specifies the exact versions of all gems you use. Because some gems depend on other gems, Ruby will install all you need automatically. The file also contains specific version numbers. It can be used to make sure that everyone within a team is working with the same versions of gems. The file is auto-generated. Do not edit this file.
A command is a specific instruction given to a computer application to perform some kind of task or function.
1.2.2 Important Rails Commands Here is a summary of important commands that can be used as you develop your Ruby on Rails app. You must be in the root directory of your project to run any of these commands (with the exception of the rails new command). The project or application root directory is the folder containing all the subfolders described above (app, config, etc.).
16
Ruby Basics Concept
Usage
Description
Create a new app
rails new name
Create a new Ruby on Rails application with the given name here. This will give you the basic structure to immediately get started. After this command has successfully run your application is in a folder with the same name you gave the application. You have to cd into that folder.
Start the server
rails server
You have to start the server in order for your application to respond to your requests. Starting the server might take some time. When it is done, you can access your application underlocalhost:3000 in the browser of your choice. In order to stop the server, go to the console where it is running and press Ctrl +C
Scaffolding
rails generate scaffold name attribute:type
The scaffold command magically generates all the common things needed for a new resource for you! This includes controllers, models and views. It also creates the following basic actions: create a new resource, edit a resource, show a resource, and delete a resource. That’s all the basics you need. Take this example: rails generate scaffold product name:string price:integer Now you can create new products, edit them, view them and delete them if you don’t need them anymore. Nothing stops you from creating a full fledged web shop now ;-)
Run migrations
rake db:migrate
When you add a new migration, for example by creating a new scaffold, the migration has to be applied to your database. The command is used to update your database.
Install dependencies
bundle install
If you just added a new gem to your Gemfile you should run bundle install to install it. Don’t forget to restart your server afterwards!
17
Basic Computer Coding: Ruby Check dependencies
bundle check
Checks if the dependencies listed in Gemfile are satisfied by currently installed gems
Show existing routes
rake routes
Shows complete list of available routes in your application.
1.2.3 ERB: Embedded Ruby In your views (that is, under app/views in your Rails app) you will find .html.erb files. ERB stands for Embedded RuBy. This just means that Rails processes some special tags in those files and produces HTML output to send back to the user. There are two ERB tags that you need to remember: and . Notice that the difference is the = in the first tag. Tag
Examples
Description
It runs the Ruby code and inserts the result to the HTML at that position. You can put any kind of Ruby code between , for instance, will translate to 27 in the page that the user is viewing. However, typically this tag is used to display some data from a model, such as the price of a product, as shown in the example here.
The Ruby code between the
Hello Admin!
the result will not be inserted at this point in the HTML. Therefore these tags are most commonly used for control flow structures such as an if statement in the example, or loops.
18
Ruby Basics
1.2.4 Editor tips When you write code you will be using a text editor. Of course each text editor is different and configurable. Here are just some functions and their most general short cuts. All of them work in Sublime Text 2. Your editor may differ! The shortcuts listed here are for Linux/Windows. On a Mac you will have to replace Ctrl with Cmd. Function
Shortcut
Description
Save file
Ctrl + S
Saves the currently open file. If it was a new file you may also be asked where to save it.
Undo
Ctrl + Z
Undo the last change you made to the current file. Can be applied multiple times in succession to undo multiple changes.
Redo
Ctrl + Y
Redo what you just undid with undo, can also be done multiple times.
or Ctrl + Shift +Z Find in File
Ctrl + F
Search for a character sequence within the currently open file. Hit Enter to progress to the next match.
Find in all Files
Ctrl + Shift +F
Search for a character sequence in all files of the project.
Replace
Ctrl + H
Replace occurrences of the supplied character sequence with the other supplied character sequence. Useful when renaming something.
or Ctrl + R Copy
Ctrl + C
Copy the currently highlighted text into the clipboard.
Cut
Ctrl + X
Copy the highlighted text into the clipboard but delete it.
Paste
Ctrl + V
Insert whatever currently is in the clipboard (through Copy or Cut) at the current caret position. Can insert multiple times.
New File
Ctrl + N
Create a new empty file.
Search and open file
Ctrl + P
Search for a file giving part of its name (fuzzy search). Pressing enter will open the selected file.
Comment
Ctrl + /
Marks the selected text as a comment, which means that it will be ignored. Useful when you want to see how something behaves or looks without a specific section of code being run.
19
Basic Computer Coding: Ruby
1.3 THE HISTORY OF RUBY The Ruby language is 21 years old. Its strong community and adoption by the open source community has kept this language steady and improving. Ruby has changed drastically over the years. It has grown from a young child to the strong adult that it is today. But it didn’t get that way overnight. Let’s take a look at the life of the Ruby programming language.
Birth (1993) Object-oriented programming (OOP) refers to a type of computer programming (software design) in which programmers define not only the data type of a data structure, but also the types of operations (functions) that can be applied to the data structure.
Ruby was born in 1993, conceived in a discussion between Yukihiro Matsumoto (“Matz”) and a colleague. They were discussing the possibility of an object-oriented scripting-language. Matz stated in ruby-talk: 00382 that he knew Perl, but did not like it very much; that it had the smell of a “toy” language. He also discussed that he knew Python, but didn’t like it because it wasn’t a true object-oriented programming language. Matz wanted a language perfect for his needs: ■
Syntactically Simple
■
Truly Object-Oriented
■
Having Iterators and Closures
■
Exception Handling
■
Garbage Collection
■
Portable
1.3.1 Toddler Years Ruby became a toddler (n.: a young child who is just beginning to walk) when Ruby 1.0 was released in December, 1996. Ruby 1.1 shortly
20
Ruby Basics
followed in August of 1997, and the first stable version of Ruby (1.2) was released in December of 1998. At this point in time, Ruby was localized to Japan only, but it would soon spread to other parts of the world…
Primary School Years In 1998, Matz created a simple English homepage for Ruby. However, Ruby was still much localized to Japan. In trying to further this expansion, the first English language Ruby mailing list, Ruby-Talk, was created. Ruby was beginning to spread beyond Japan. Ruby-Talk is still very active today, and you can subscribe to it here. In October of 1999, Yukihiro Matsumoto and Keiju Ishitsuka wrote the first book on the Ruby programming language: The Object-oriented Scripting Language Ruby. Ruby was beginning to get very popular in Japan, and spreading rapidly to English-speaking countries. In 2001, the first English book on Ruby, Programming Ruby (“The Pickaxe”), was published in 2001. With this new information on Ruby, many more people were able to learn the language. Including: ■
Duck Typing (looks like a duck, swims like a duck, quacks like a duck: it’s a duck)
■
Fully Qualified Names (Foo::Bar)
■
Native YAML Support
■
WEBrick
■
StringIO 21
Remember Having looked around and not found a language suited for him, Yukihiro Matsumoto decided to create his own. After spending several months writing an interpreter, Matz finally published the first public version of Ruby (0.95) to various Japanese domestic newsgroups in December, 1995. You can still download the infant version of Ruby here at your own risk.
Basic Computer Coding: Ruby
Ruby 1.8 was released in 2003. This release made large amounts of changes to the agile 10-year-old language.
■
open-uri
■
PP (Pretty Printer for Hash#inspect)
■
ruby -run (UNIX commands for all! ruby -run -e mkdir foo)
■
And many other minor features
In 2004, RubyGems was released to the public. Good things started happening next…
1.3.2 The Rebellious Teenager In 2005, Ruby use took off. The reason: Ruby on Rails. This new framework changed the history of rapid web development. Ruby had been used in the past to write CGI scripts, but Ruby on Rails took this a step further. Rails has a Model-View-Controller structure that focuses on “convention over configuration”, which is great for developing web applications. People loved it. So much so that, the Ruby community was almost taken over by the Rails framework. Ruby in turn became very popular. In March of 2007, Ruby 1.8.6 was released, with 1.8.7 following in May of 2008. At this point, Ruby was at its peak. Mac OS X even began shipping with it in 2007. At this point, Ruby was 15 years old. Ruby 1.9 (development version) was released in December, 2007, then stabilized 4 years later (2011) as Ruby 1.9.3. Ruby 1.9.3 was the production version of 1.9.2. These versions brought new changes to the language, such as: ■
Significant speed improvements
■
New methods
■
New hash syntax ({ foo: ‘bar’ })
■
RubyGems included
■
New Socket API (IPv6 support) 22
Ruby Basics
■
Several random number generators
■
Regular Expression improvements
■
File loading performance improvements
■
Test::Unit Improvements
■
New encoding support
■
More string formatting tweaks
■
And so much more
Ruby was making the transition from a rebellious teenager to a strong adult as it turned 18 with Ruby 1.9.3.
Strong Adult Ruby 2.0.0 was released in February 2013 and brought many stabilizing changes to the language. Among them are: ■
More speed improvements
■
Refinements (safe monkey patching)
■
Keyword arguments
■
UTF-8 by default
■
New regular expressions engine
■
Optimized garbage collection
■
The addition of built-in syntax documentation (ri ruby:syntax)
Unlike 1.9.x, which broke numerous gems with its changes, 2.0.0 was almost completely backwards compatible with 1.9.3. In addition, Heroku, one of the leading Ruby/Rails hosts upgraded to 2.0.0 quickly, causing earlier than usual adoption by new and existing projects. The Ruby language was (and is) in its golden age. Ruby 2.1.0 was released on Christmas day of 2013. It brought several minor changes to the language. But the biggest news of 2.1.0 was semantic versioning, a way to properly version a project without breaking dependencies by accident. Ruby 2.1.1 was released on Ruby’s 21st birthday (February 24, 2014). Ruby is now legally allowed to drink in the US (not that we’d want it to). This version was mainly speed improvements and bugfixes. Shortly after 2.1.1, Ruby 2.1.2 was released in May of 2014. 2.1.2 consists of more bugfixes and is the current stable version of Ruby. 23
Basic Computer Coding: Ruby
1.3.3 The Future Ruby is a great language. Matz wanted a programming language that suited his needs, so he built one. This is an inspiring story of software development: if you can’t find something that you like, program it yourself. From 0.95 to 2.1.2, Ruby has struck the awe of those who wished to program the way they wanted, not the way the machine wanted. We can’t know the future of the Ruby language, but we can predict it based on the past. I believe that the Ruby language, and its fantastic community will continue furthering the language above and beyond what others think is possible, and projects built using it will do the same.
24
Ruby Basics
ROLE MODEL Yukihiro Matsumoto: Japanese computer scientist and software programmer
“Matsumoto Yukihiro, a.k.a. Matz, is a Japanese computer scientist and software programmer best known as the chief designer of the Ruby programming language and its reference implementation, Matz’s Ruby Interpreter (MRI). As of 2011, Matsumoto is the Chief Architect of Ruby at Heroku, an online cloud platform-as-a-service in San Francisco. He is a fellow of Rakuten Institute of Technology, a research and development organisation in Rakuten Inc. He was appointed to the role of technical advisor for VASILY, Inc. starting in June 2014.
Early life Born in Osaka Prefecture, Japan, he was raised in Tottori Prefecture from the age of four. According to an interview conducted by Japan Inc., he was a self-taught programmer until the end of high school. [2] He graduated with an information science degree from University of Tsukuba, where he was a member of Ikuo Nakata’s research lab on programming languages and compilers.
Work He works for the Japanese open source company, netlab.jp. Matsumoto is known as one of the open source evangelists in Japan. He has released several open source products, including cmail, the Emacs-based mail user agent, written entirely in Emacs Lisp. Ruby is his first piece of software that has become known outside Japan.
25
Basic Computer Coding: Ruby
Ruby Matsumoto released the first version of the Ruby programming language on 21 December 1995. He still leads the development of the language’s reference implementation, MRI (for Matz’s Ruby Interpreter).
MRuby In April 2012, Matsumoto open-sourced his work on a new implementation of Ruby called mruby.[6][7] It is a minimal implementation based on his virtual machine, called ritevm, and is designed to allow software developers to embed Ruby in other programs while keeping memory footprint small and performance optimised.
streem In December 2014, Matsumoto open-sourced his work on a new scripting language called streem, a concurrent language based on a programming model similar to shell, with influences from Ruby, Erlang and other functional programming languages.
Treasure Data Matsumoto has been listed as an investor for Treasure Data; many of the company’s programs such as Fluentd use Ruby as their primary language.
Recognition Matsumoto received the 2011 Award for the Advancement of Free Software from the Free Software Foundation (FSF) at the 2012 LibrePlanet conference at the University of Massachusetts Boston in Boston
Personal life Matsumoto is married and has four children. He is a member of The Church of Jesus Christ of Latter-day Saints, did standard service as a missionary and is now a counselor in the bishopric in his church ward. 26
Ruby Basics
SUMMARY ■
Ruby is a cross-platform interpreted language which has many features in common with other ‘scripting’ languages such as Perl and Python.
■
An array is an ordered collection of items which is indexed by numbers. So an array contains multiple objects that are mostly related to each other. So what could you do? You could store a collection of the names of your favorite fruits and name it fruits.
■
Ruby in Steel is a Windows-based IDE which comes with an all-in-one installer to install Ruby, Visual Studio, Ruby in Steel and various other optional packages including Rails.
■
The Ruby language is 21 years old. Its strong community and adoption by the open source community has kept this language steady and improving. Ruby has changed drastically over the years. It has grown from a young child to the strong adult that it is today.
■
Rails has a Model-View-Controller structure that focuses on “convention over configuration”, which is great for developing web applications.
■
Ruby 2.1.0 was released on Christmas day of 2013. It brought several minor changes to the language. But the biggest news of 2.1.0 was semantic versioning, a way to properly version a project without breaking dependencies by accident.
■
Ruby is a great language. Matz wanted a programming language that suited his needs, so he built one. This is an inspiring story of software development: if you can’t find something that you like, program it yourself.
27
Basic Computer Coding: Ruby
KNOWLEDGE CHECK 1.
2.
3.
4.
5.
Ruby was developed in mid a.
1960s
b.
1970s
c.
1980s
d.
1990s
Programming language which is an open-source, object oriented programming language with simple syntax similar to Perl and Python is a.
C
b.
C++
c.
Java
d.
Ruby
A web application development framework written in Ruby language is a.
Rail
b.
Ada
c.
Pascal
d.
Java
Ruby on Rails was used to build user’s interface of a.
Twitter
b.
Facebook
c.
Wikipedia
d.
Google
Rails’ application framework is called ………………. a.
ActionPack
b.
ActiveRecord
c.
a web page
d.
an object
28
Ruby Basics
REVIEW QUESTIONS 1.
Define the Ruby code.
2.
Focus on frameworks for Ruby programming.
3.
Define html.erb files.
4.
What will the following code return? true and 0 && !nil and 3 > 2
5.
Explain the strings.
Check your Result 1. (d)
2. (d)
3. (a)
29
4. (a)
5. (a)
Basic Computer Coding: Ruby
REFERENCES 1.
http://www.pragtob.info/rails-beginner-cheatsheet/
2.
h t t p : / / w w w. t r o u b l e s h o o t e r s . c o m / c o d e c o r n / r u b y / basictutorial.htm
3.
https://docs.chef.io/ruby.html
4.
https://medium.com/the-renaissance-developer/ruby-101the-basics-f10961f990ac
5.
https://medium.freecodecamp.org/understanding-thebasics-of-ruby-on-rails-http-mvc-and-routes-359b8d809c7a
6.
https://rubygarage.org/blog/how-to-learn-ruby-on-rails
7.
https://www.coursera.org/lecture/ruby-on-rails-intro/ ruby-basics-2Ss3j
8.
https://www.gia.edu/ruby-history-lore
9.
https://www.javatpoint.com/ruby-tutorial
10.
https://www.learneroo.com/modules/61/nodes/338
11.
h t t p s : / / w w w. o r e i l l y. c o m / l i b r a r y / v i e w / r u b y - o n railstm/9780134597355/ch06.html
12.
h t t p s : / / w w w. p h u s i o n p a s s e n g e r . c o m / l i b r a r y / walkthroughs/basics/ruby/fundamental_concepts.html
13.
h t t p s : / / w w w. s a p p h i r e s t e e l . c o m / I M G / p d f / LittleBookOfRuby.pdf
14.
https://www.sitepoint.com/history-ruby/
15.
https://www.softcover.io/read/e8898d1d/learn-rails-1/88_ Learn_Ruby
16.
h t t p s : / / w w w. t h e o d i n p r o j e c t . c o m / c o u r s e s / w e b development-101/lessons/ruby-basics
17.
https://www.tutorialspoint.com/ruby/
30
CHAPTER 2
WORKING WITH STRINGS, OBJECTS, AND VARIABLES “Web servers are written in C, and if they’re not, they’re written in Java or C++, which are C derivatives, or Python or Ruby, which are implemented in C.” ―Rob Pike
Learning Objectives After studying this chapter, you will be able to: ■
Discuss about Ruby – strings
■
Explain objects and methods
■
Describe variable in Ruby
Basic Computer Coding: Ruby
INTRODUCTION Strings are one of the most important data types in computer languages. A string is a sequence of Unicode characters. It is a data type that stores a sequence of data values in which elements usually stand for characters according to a character encoding. When a string appears literally in source code, it is known as a string literal. Ruby is an object-oriented programming language. This means that in Ruby programs we work with objects. From a language programmer’s point of view a Ruby program is a stream of tokens. These tokens are Ruby keywords, operators, various delimiters or literals. From a semantic point of view a Ruby program consists of objects. These objects are created and modified during the lifetime of a Ruby script.
There are two kinds of objects: built-in objects and custom objects. Built-in objects are predefined objects that all programmers can use. They are available with the core of the Ruby language or from various libraries. Custom objects are created by application programmers for their application domains. A variable is a place to store data. Each variable is given a unique name. There are some naming conventions which apply to variable names. Variables hold objects. More precisely, they refer to a specific object located in computer memory. Each object is of certain data type. There are built-in data types and there are custom-built data 32
Working with Strings, Objects, and Variables
types. Ruby belongs to the family of dynamic languages. Unlike strongly typed languages like Java, C or Pascal, dynamic languages do not declare a variable to be of certain data type. Instead of that, the interpreter determines the data type at the moment of the assignment. Variables in Ruby can contain different values and different types of values over time.
2.1 RUBY - STRINGS A String object in Ruby holds and manipulates an arbitrary sequence of one or more bytes, typically representing characters that represent human language. The simplest string literals are enclosed in single quotes (the apostrophe character). The text within the quote marks is the value of the string − ‘This is a simple Ruby string literal’ If you need to place an apostrophe within a single-quoted string literal, precede it with a backslash, so that the Ruby interpreter does not think that it terminates the string − ‘Won\’t you read O\’Reilly\’s book?’ The backslash also works to escape another backslash, so that the second backslash is not itself interpreted as an escape character.
2.1.1 Concatenation One of the most basic things you will find yourself doing with strings is concatenation. This is where you join two strings together. There are a few different ways to do this in Ruby. Firstly you can join two strings together using the + operator:
If you already have a string you can append another string using the ``` operator: 33
Basic Computer Coding: Ruby
You can also multiple a string by an integer to return three copies of that string as a new string:
2.1.2 Case We can convert a string into capital case by calling the capitalize method:
When you call a method on a string, such as capitalize, you will be returned a new string. For example, try the following in IRB:
Now if you puts the name variable, what do you think it will be?
34
Working with Strings, Objects, and Variables
When you call a method on a String object it creates a new string, rather than changing the existing one. To modify the original instance we can call the same method but with a !:
If you want to convert a string to lowercase you can call the downcase method:
Alternatively you can covert a string to uppercase using the upcase method:
2.1.3 Length If you need to count the number of characters in a string you can call use the length method:
35
Uppercase characters are capital letters; lowercase characters are small letters.
Basic Computer Coding: Ruby
2.1.4 Strip Whenever you accept input from a user you should make sure they haven’t included any whitespace. You can remove white space using the strip method:
If you want to modify the current instance of the string rather than create a new string, you should call the method with a !:
Alternatively you can only remove whitespace from the left or the right of the string by calling lstrip or rstrip.
2.2 OBJECTS AND METHODS “Everything in Ruby is an Object” is something you’ll hear rather frequently. “Pretty much everything else is a method” could also be said. The goal here is for you to see the Matrix... that everything in Ruby is an Object, every object has a class, and being a part of that class gives the object lots of cool methods that it can use to ask questions or do things. Being incredibly object-oriented gives Ruby lots of power and makes your life easier. Think of every “thing” in Ruby as a having more than meets the eye. The number 12 is more than just a number... It’s an object and Ruby lets you do all kinds of interesting things to it like adding and multiplying and asking it questions like > 12.class or > 12+3 36
Working with Strings, Objects, and Variables
Ruby gives all objects a bunch of neat methods. If you ever want to know what an object’s methods are, just use the #methods method! Asking > 12345.methods in IRB will return a whole bunch of methods that you can try out on the number 12345. You’ll also see that the basic operators like + and - and / are all methods too (they’re included in that list). You can call them using the dot > 1.+2 like any other method or, luckily for you, Ruby made some special shortcuts for them so you can just use them as you have been: > 1+2 Some methods ask true/false questions, and are usually named with a question mark at the end like #is_a?, which asks whether an object is a type of something else, e.g. 1.is_a?Integer returns true while “hihi”.is_a?Integer returns false You’ll get used to that naming convention. Methods like #is_a?, which tell you something about the object itself, are called Reflection Methods (as in, “the object quietly reflected on its nature and told me that it is indeed an Integer”). ::class was another one we saw, where the object will tell you what class it is. What is a method? A method is just a function or a black box. You put the thing on the left in, and it spits something out on the right. Every method returns something, even if it’s just nil. Some methods are more useful for their Side Effects than the thing they actually return, like #puts That’s why when you say > puts “hi” in IRB, you’ll see a little => nil down below... the method prints out your string as a “side effect” and then returns nil after it’s done. When you write your own methods, if you forget to think about the return statement,
37
Black box is a device, system or object which can be viewed in terms of its inputs and outputs (or transfer characteristics), without any knowledge of its internal workings.
Basic Computer Coding: Ruby
sometimes you’ll get some wierd behavior so always think about what’s going in and what’s coming out of a method. Methods can take inputs too, which are included in parentheses to the right of the method name (though they can be omitted, as you do with > puts(“hi”) becoming > puts “hi”.. it’s okay to be lazy, as long as you know what you’re doing). Going back to the addition example, > 1+2==3 is asking whether 1+2 will equal 3 (it returns => true), but it can more explicitly be written > 1.+(2).==(3) So, in this case, you can see there’s more going on than meets the eye at first.
Remember When you run a normal method in IRB, it will output whatever the method returns but it will preserve the original object.
That example also shows Method Chaining, which is when you stick a bunch of methods onto each other. It behaves like you’d expect -evaluate the thing on the left first, pass whatever it returns to the method on the right and keep going. So > 1+2==3 first evaluates 1+2 to be 3 and then evaluates 3==3 which is true This is great because it lets you take what would normally be many lines of code and combine them into one elegant expression. Bang Methods are finished with an exclamation point ! like #sort!, and they actually modify the original object. The exclamation point lets you know you’re in dangerous territory. Bang methods save over the original object (they are “destructive”): > my_numbers = [1,5,3,2] => [1, 5, 3, 2] > my_numbers.sort => [1, 2, 3, 5] > my_numbers => [1, 5, 3, 2] 38
# still unsorted
Working with Strings, Objects, and Variables
> my_numbers.sort! => [1, 2, 3, 5] > my_numbers => [1, 2, 3, 5]
# overwrote the original my_numbers object!
Methods ending with a question mark ? return true or false. Let’s answer the question, “Where did all those methods come from?” Classes are like umbrellas that let us give an object general behaviors just based on what it is. An object is an instance of a class -- you (yes, you) are an instance of the Person class. There are lots of behaviors (methods) that you can do just by virtue of being a Person... #laugh, #jump, speak(“hello”) This is really useful in programming because you often need to create lots of instances of something and it’s silly to have to rewrite all the methods you want all of them to have anyway, so you write them at the class level and all the instances get to use them. Instances of a class get to inherit the behaviors of that class. Inheritance works for classes too! Your class Person has lots of methods but many of them are inherited just by virtue of you also being a Mammal or even just a LivingThing You get to use all the methods of your ancestor classes An interesting exercise to try in Ruby is to use the method ::superclass to ask a class what its parent is. If you just keep on going and going, you’ll see that everything eventually inherits from BasicObject, which originates most of the methods you have access to in the original object: > 1.class.superclass.superclass.superclass => BasicObject > BasicObject.methods => # giant list of methods Random Note: Running the ::methods method on a class only returns the class methods, whereas ::instance_methods will return all methods available to any instance of that class (so String.methods will return a list of class methods, while “hello”.methodswill return a longer list that is the same as String.instance_methods).
39
Basic Computer Coding: Ruby
Other Random Note: Use object_id to see an object’s id, and this can be useful if you’re running into odd errors where you thought you were modifying and object but it’s not changing. If you debug and look at the id’s along the way, you may find that you’re actually only modifying a COPY of that object. To Write Your Own Methods, just use the syntax def methodname(argument1, argument2), though the parentheses around the arguments are optional. The method will return (“spit out”) either whatever follows the return statement or the result of the last piece of code that was evaluated (an Implicit Return statement). You call the inputs by whatever name you defined them at the top. You can write methods in IRB... it will let you use multiple lines if it detects that you have unfinished business (a def without an end or unclosed parentheses): > def speak(words) >
puts words
>
return true
> end => nil
# ignore this
> speak(“hello!”) hello! => true What if you want to assume that the input to a method is a particular value if there hasn’t been any supplied? That’s easy, just specify the Default Input by assigning it to something where it’s listed as an input: > def speak(words=”shhhhh”) >
puts words
> end => nil > speak
# implicitly returns what puts returns... nil! # ignore this # no input
shhhhh => nil
40
Working with Strings, Objects, and Variables
2.2.1 Objects and Attributes If the object that you’re attempting to bind is neither Serializable nor Referenceable, then you can still bind it if it has attributes, provided that binding DirContext objects is a feature supported by the underlying service provider. Sun’s LDAP service provider supports this feature.
Interoperability Binding DirContext objects is especially useful for interoperability with non-Java applications. An object is represented by a set of attributes, which can be read and used by non-Java applications from the directory. The same attributes can also be read and interpreted by a JNDI service provider, which, in conjunction with an object factory, converts them into a Java object. For example, an object might have, as some of its attribute values, URLs that the JNDI service could use to generate an instance of a Java object that the application could use. These same URLs could be used also by nonJava applications.
Binding an Object by Using Its Attributes The following example shows a Drink class that implements the DirContext interface. Most DirContext methods are not used by this example and so simply throw anOperationNotSupportedException
.
public class Drink implements DirContext { String type; 41
Service provider can be an organizational subunit, it is usually a third party or outsourced supplier, including telecommunications service providers (TSPs), application service providers (ASPs), storage service providers (SSPs), and internet service providers (ISPs).
Basic Computer Coding: Ruby
Attributes myAttrs; public Drink(String d) { type = d; myAttrs = new BasicAttributes(true); // Case ignore Attribute oc = new BasicAttribute(“objectclass”); oc.add(“extensibleObject”); oc.add(“top”); myAttrs.put(oc); myAttrs.put(“drinkType”, d); }
{
public Attributes getAttributes(String name) throws NamingException if (! name.equals(“”)) { throw new NameNotFoundException(); } return (Attributes)myAttrs.clone(); } public String toString() { return type; }
... } The Drink class contains the “objectclass” and “drinkType” attributes. The “objectclass” attribute contains two values: “top” and “extensibleObject”. The “drinkType” attribute is set by using the string passed to the Drink constructor. For example, if the instance was created by using new Drink(“water”), then its “drinkType” attribute will have the value “water”. 42
Working with Strings, Objects, and Variables
The following example creates an instance of to add it Drink and invokes Context.bind() to the directory. // Create the object to be bound Drink dr = new Drink(“water”); // Perform the bind ctx.bind(“cn=favDrink”, dr); When the object is bound, its attributes are Directory is a file extracted and stored in the directory. system cataloging When that object is subsequently looked up from the directory, its corresponding object factory will be used to return an instance of the object. The object factory is identified by theContext. environment property OBJECT_FACTORIES when the initial context for reading the object is created. Hashtable env = ...; // Add property so that the object factory can be found e n v. p u t ( C o n t e x t . O B J E C T _ FA C T O R I E S , “DrinkFactory”); // Create the initial context DirContext ctx = new InitialDirContext(env); // Read back the object Drink dr2 = (Drink) ctx.lookup(“cn=favDrink”); System.out.println(dr2); This produces the following output, “water”, produced by Drink.toString(). # java DirObj water
43
structure which contains references to other computer files, and possibly other directories.
Basic Computer Coding: Ruby
From the perspective of the application using the JNDI, it is dealing only with bind() and lookup(). The service provider takes care of getting the attributes from the object and converting them to/from the actual object itself. Note that you can store a DirContext object in the directory only if the underlying service provider supports that.
2.3 VARIABLE IN RUBY Variable is a symbol or name that stands for a value. Variables locate in memory locations and are used to store values such as numeric values, characters, character strings, or memory addresses so that they can be used in any part of the program.
We have discussed the following types of variables and constants supported by Ruby : ■
Local Variables
■
Instance Variables
■
Class Variables
■
Global Variables
■
Constants
2.3.1 Local Variable A local variable name must start with a lowercase letter (a-z) or underscore (_) with the eight-bit set. 44
Working with Strings, Objects, and Variables
Local Variable Scope A local variable is only accessible from within the block of its initialization. See the following example: In the following example, there are three local variables called color. One is assigned the value, ‘Red’ within the ‘main scope’ of the program; two others are assigned integers within the scope of two separate methods. As each local variable has a different scope, the assignments have no affect on the other local variables with the same name in different scopes. We have verified it by calling the methods at the end of the program.: Example: color = “Red” def method1 color = 192 puts(“Color Value in method1 : “,color) end
def method2 color = 255 puts(“Color Value method2: “,color) end
method1 method2 method1 puts(“Color Value outside methods : “+color) Copy 45
Basic Computer Coding: Ruby
Output: H:\>ruby abc.rb Color Value in method1 : 192 Color Value method2: 255 Remember Local variable names must begin with either an underscore or a lower case letter.
Color Value in method1 : 192 Color Value outside methods : Red
Local Variables and Methods In Ruby, local variable names and method names are nearly identical. If you have not assigned to one of these ambiguous names ruby will assume you wish to call a method. Once you have assigned to the name ruby will assume you wish to reference a local variable. The local variable is created when the parser encounters the assignment, not when the assignment occurs: a = 0 if false # does not assign to a p local_variables # prints [:a] p a # prints nil Copy def big_calculation 42 # pretend this takes a long time end big_calculation = big_calculation() Copy
46
Working with Strings, Objects, and Variables
Now any reference to big_calculation is considered a local variable and will be cached. To call the method, use self.big_calculation. You can force a method call by using empty argument parentheses as shown above or by using an explicit receiver like self. Using an explicit receiver may raise a NameError if the method’s visibility is not public. Another commonly confusing case is when using a modifier if: p a if a = 0.zero? Copy Rather than printing “true” you receive a NameError, “undefined local variable or method `a’”. Since ruby parses the bare a left of the if first and has not yet seen an assignment to it assumes you wish to call a method. Ruby then sees the assignment to a and will assume you are referencing a local method. The confusion comes from the out-of-order execution of the expression. First, the local variable is assigned to then you attempt to call a nonexistent method.
2.3.2 Instance Variables Instance variables are shared across all methods for the same object. The instance variable name must start with ‘@’ character, otherwise instance variable names follow the rules as a local variable name. Syntax: @insvar In the following example, Student.new creates a new object - an instance of the class Student. 47
Parenthesis is a tall, curvy punctuation mark used to set off material that isn’t fundamental to the main topic, like an afterthought or an aside (or a funny joke).
Basic Computer Coding: Ruby
The instance variables @student_id and @student_name. class Student def initialize(student_id, student_name) @student_id = student_id @student_name = student_name end
def show puts “Student Name and ID : “ puts(@student_id, @student_name) end end Student.new(1, “Sara”).show Student.new(2, “Raju”).show Copy Output: Student Name and ID : 1 Sara Student Name and ID : 2 Raju Note : An uninitialized instance variable has a value of nil.
48
Working with Strings, Objects, and Variables
2.3.3 Class Variables Class variables are shared between a class, its subclasses, and its instances. A class variable must start with a @@ (two “at” signs). The rest of the name follows the same rules as instance variables. Syntax: @@classvar The following example shows that all classes change the same variable. Class variables behave like global variables which are visible only in the inheritance tree. Because Ruby resolves variables by looking up the inheritance tree first, this can cause problems if two subclasses both add a class variable with the same name. Example: class School @@no_off_students = 650 end # class V sub-class of School class V < School @@no_off_students = 75 end # class VI sub-class of School class VI < School @@no_off_students = 80 end puts School.class_eval(“@@no_off_students”) puts V.class_eval(“@@no_off_students”) puts VI.class_eval(“@@no_off_students”) Copy 49
Remember Class variables must be initialized at creation time.
Basic Computer Coding: Ruby
Output: 80 80 80 Using the class variable @@no_of_customers, you can determine the number of objects that are being created. This enables in deriving the number of customers. class Customer @@no_of_customers = 0 end
2.3.4 Global Variables In Ruby a global variables start with a $ (dollar sign). The rest of the name follows the same rules as instance variables. Global variables are accessible everywhere. Syntax: $globalvar Example: $global = 0
class C puts “in a class: #{$global}”
def my_method puts “in a method: #{$global}”
50
Working with Strings, Objects, and Variables
$global = $global + 1 $other_global = 3 end end
C.new.my_method
puts “at top-level, $global: #{$global}, $other_ global: #{$other_global}”
Copy Output: in a class: 0 in a method: 0 at top-level, $global: 1, $other_global: 3 An uninitialized global variable has a value of nil. Ruby has some special globals that behave differently depending on context such as the regular expression match variables or that have a side-effect when assigned to.
2.3.5 Ruby Constants A variable whose name begins with an uppercase letter (A-Z) is a constant. A constant can be reassigned a value after its initialization, but doing so will generate a warning. Every class is a constant. 51
Initialization is the assignment of an initial value for a data object or variable.
Basic Computer Coding: Ruby
Trying to access an uninitialized constant raises the NameError exception. Syntax: ABCD Example : class Student NO_Students = 800 end puts ‘No of students in the school : ‘, Student::NO_Students Copy Here NO_Students is the constant. Output: No of students in the school : 800 Table 1: Ruby- Pseudo Variables
Name
Description
self
Execution context of the current method.
nil
Expresses nothing. nil also is considered to be false, and every other value is considered to be true in Ruby.
true
Expresses true.
false
Expresses false.
$1, $2 ... $9 These are contents of capturing groups for regular expression matches. They are local to the current thread and stack frame!
52
Working with Strings, Objects, and Variables
Table 2: Ruby- Pre-defined Variables
Name
Description
$!
The exception information message set by the last ‘raise’ (last exception thrown).
$@
Array of the backtrace of the last exception thrown.
$&
The string matched by the last successful pattern match in this scope.
$`
The string to the left of the last successful match.
$’
The string to the right of the last successful match.
$+
The last group of the last successful match.
$1 to $9
The Nth group of the last successful regexp match.
$~
The information about the last match in the current scope.
$=
The flag for case insensitive, nil by default (deprecated).
$/
The input record separator, newline by default.
$\
The output record separator for the print and IO#write. Default is nil.
$,
The output field separator for the print and Array#join.
$;
The default separator for String#split.
$.
The current input line number of the last file that was read.
$
Keep programming! In other words, if both these statements are true, execute the code in the block. You can have more than two statements separated by &&: if a == 10 && b == 27 && c == 43 && d == -14 print sum = a + b + c + d end If all these statements are true, sum will be printed. You can also use the keyword and instead of &&. if ruby == “nifty” and programming == “fun” and weather == “nice” puts “Stop programming and go outside for a break!” end Another choice is the || operator; a synonym for this operator is or. When you use || or or, if any of the statements are true, the code executes: if ruby == “nifty” or programming == “fun” puts “Keep programming!” end If either of the two statements is true, the string keep programming! will print. Are more than two statements OK? Of course: if a == 10 || b == 27 || c = 43 || d = -14 print sum = a + b + c + d end || and or, and && and and, are considered logical operators. Lots of other operators are possible, too, such as: delete_record if record != 0x8ff # not equal to 68
Implementing Conditional Logic
if amt > 1.00 then desc = “dollars” end # greater than desc = “cents” if amt < 1.00 # less than if height >= 6 then print “L or XL” end # greater than or equal to print “shrimpy” if weight high The range 1..3 means a range of numbers from 1 to 3, inclusive. Because scale equals 8, scale matches the range 8..9 and case returns the string high. However, when you use three dots as in the range 1...5, the ending value 5 is excluded. The sets of dots, .. and ..., are called range operators; two dots includes all the numbers in the range, and three dots excludes the last value in the range. Underneath the hood, case uses the === operator from Range to test whether a value is a member of or included in a range. 72
Implementing Conditional Logic
# case_statement.rb
a=5
case a when 5 puts “a is 5” when 6 puts “a is 6” else puts “a is neither 5, nor 6” end
3.1.3 The While Loop A while loop executes the code it contains as long as its conditional statement remains true. The following piece of code initializes a counter i to 0 and sets up an array containing four elements called breeds (horse breeds).It also creates a temporary array named temp. The following few paragraphs are fairly fundamental, and are provided for beginning programmers. If you already have plenty of programming under your belt, skip ahead to the code itself. The while loop will execute as long as its conditional (i < breeds.size) is true. The i variable starts out its little life equaling 0, and the size or length of the breeds array is 4. As you come to the end of the loop, i is 73
Basic Computer Coding: Ruby
incremented by 1, and then control returns to the top of the loop. In the first loop, i equals 0, and is fed as 0 as an argument to breeds[i], which retrieves the first element (numbered 0).This is the string value quarter. That element is appended via 4 temp = []
while i < breeds.size do temp [“Appalosa”, “Arabian”, “Paint”, “Quarter”] breeds.replace( temp ) p breeds # => [“Appalosa”, “Arabian”, “Paint”, “Quarter”]
74
Implementing Conditional Logic
By the way, the do is optional here, so this form of the loop is legitimate, too: while i < breeds.size temp [“Quarter”, “Arabian”] When the if modifier following break found Arabian in the temp array, it broke out of the loop right then. The next statement (which calls the p method) shows that we didn’t get very far appending elements to the temp array.
Unless and Until The unless and until statements are similar to if and while, except they are executed while their conditionals are false, whereas if and while statements are executed while their conditionals are true. Of course, if and while are used more frequently than unless and until, but the nice thing about having them is that Ruby offers you more expressiveness. An unless statement is really like a negated if statement. We’ll show you an if statement first: if lang == “de” dog = “Hund” else dog = “dog” end Now I’ll translate it into unless: unless lang == “de” dog = “dog” else dog = “Hund” 76
Implementing Conditional Logic
end This example is saying, in effect, that unless the value of lang is de, then dog will be assigned the value of dog; otherwise, assign dog the value Hund. See how the statements are reversed? In the if statement, the assignment of Hund to dog comes first; in the unless example, the assignment of dog to dog comes first. Like if, you can also use unless as a statement modifier: puts age += 1 unless age > 29 As unless is a negated form of if, until is really a negated form of while. Compare the following statements. The first is a while loop: weight = 150 while weight < 200 do puts “Weight: “ + weight.to_s weight += 5 end Here is the same logic expressed with until: weight = 150 until weight == 200 do puts “Weight: “ + weight.to_s weight += 5 end And like while, you have another form you can use with until—that is, with begin/ end: weight = 150 begin puts “Weight: “ + weight.to_s weight += 5 end until weight == 200 In this form, the statements in the loop are evaluated once before the conditional is checked. And finally, like while, you can also use until as a statement modifier: puts age += 1 until age > 28 77
Basic Computer Coding: Ruby
3.2 COMPARISON OPERATORS Comparison operators take simple values (numbers or strings) as arguments and used to check for equality between two values. Ruby provides following comparison operators: Operator
Name
Example
Result
==
Equal
x==y
True if x is exactly equal to y.
!=
Not equal
x!=y
True if x is exactly not equal to y.
>
Greater than
x>y
Teue if x is greater than y.
=y
True if x is greater than or equal to y.
true
True if two things are same object.
obj1. equal?
equal?
1.eql? 1.0 #=> false
obj2
val = 10 => 10 val.equal?(10) => true
Example: Equality test puts (“Test two numbers for equality with ==, !=, or ”) puts 14 == 16 puts 14 != 16 puts 14 14 78
Implementing Conditional Logic
puts 14 12 puts 14 16 Output: Test two numbers for equality with ==, !=, or false true 0 1 -1 Example: eql? and eqlity? operators irb(main):023:0> 1 == 1.0 => true irb(main):024:0> 1.eql?1.0 => false irb(main):025:0> obj1 = “123” => “123” irb(main):026:0> obj2 = obj1.dup => “123” irb(main):027:0> obj1 == obj2 => true irb(main):028:0> obj1.equal?obj2 => false irb(main):029:0> obj1.equal?obj1 => true irb(main):030:0> Example: Equal, less than, or greater than each other puts (“Test if two numbers are equal, less than, or greater than each other”) puts 14 < 16 79
Basic Computer Coding: Ruby
puts 14 < 14 puts 14 12.5 puts 14.0 >= 14 Output: Test if two numbers are equal, less than, or greater than each other true false true true true
Example: Spaceship operator returns -1, 0, or 1 puts (“the (spaceship operator) returns -1, 0, or 1,”) puts 2 3 puts 2 2 puts 3 2 Output: the (spaceship operator) returns -1, 0, or 1, -1 0 1 Example: Test the value in a range puts (“test if a value is in a range”) puts (12...16) === 8 puts (12...16) === 14 puts (12...16) === 16 puts (12...14) === 12 80
Implementing Conditional Logic
puts (12...16) === 14 Output: test if a value is in a range false true false true true
3.3 ASSIGNMENT OPERATORS In Ruby assignment operator is done using the equal operator “=”. This is applicable both for variables and objects, as strings, floats, and integers are actually objects in Ruby, you’re always assigning objects. Operator
Name
Description
=
Equal operator Simple assignment “=” operator, Assigns values from right side operands to left side operand
z = x + y will assign value of a + b into c
+=
Add AND
Adds right operand to the left operand and assign the result to left operand
x += y is equivalent to x=x+y
-=
Subtract AND
Subtracts right operand from the left operand and assign the result to left operand
x -= y is equivalent to x=x-y
*=
Multiply AND
Multiplies right operand x *= y is equivalent to with the left operand and x = x * y assign the result to left operand
/=
Divide AND
Divides left operand with the right operand and assign the result to left operand
81
Example
x /= y is equivalent to x=x/y
Basic Computer Coding: Ruby %=
Modulus AND Takes modulus using two operands and assign the result to left operand
x %= y is equivalent to x = x % y
**=
Exponent AND
x **= y is equivalent to x = x ** y
Performs exponential calculation on operators and assign value to the left operand
Example: Ruby assignment operator puts (“assignment operator in Ruby”) x = 47 puts (“abbreviated assignment add”) puts x += 20 puts (“abbreviated assignment subtract”) puts x -= 20 puts (“abbreviated assignment multiply”) puts x *= 4 puts (“abbreviated assignment divide”) puts x /= 4 puts (“abbreviated assignment modulus”) puts x %= 6 puts (“abbreviated assignment exponent”) puts x **= 4 Output: assignment operator in Ruby abbreviated assignment add 67 abbreviated assignment subtract 47 abbreviated assignment multiply 188 abbreviated assignment divide 47 82
Implementing Conditional Logic
abbreviated assignment modulus 5 abbreviated assignment exponent 625
3.4 LOGICAL OPERATORS The standard logical operators and, or and not are supported by Ruby. Logical operators first convert their operands to boolean values and then perform the respective comparison.
3.4.1 Logical and The binary “and” operator returns the logical conjunction of its two operands. The condition becomes true if both the operands are true. It is the same as “&&” but with a lower precedence.
This above pictorial helps you to understand the concept of LOGICAL AND operation with an analogy of taps and water. In case-1 of the picture, both of the taps are closed, so the water is not flowing down. Which 83
Logical conjunction is an operation on two logical values, typically the values of two propositions, that produces a value of true if and only if both of its operands are true.
Basic Computer Coding: Ruby
explains that if both of conditions are FALSE or 0, the return is FALSE or 0. In case-2 of the picture, one of the taps are closed, even then, the water is not flowing down. Which explains that even if any of conditions are FALSE or 0, the return is FALSE or 0. case-3 of the picture resembles CASE -2. In case-4 of the picture, both of the taps are open, so the water is flowing down. Which explains that if both of conditions are TRUE or 1, the return is TRUE or 1. So we can conclude that if and only if, both of the conditions are TRUE or 1, LOGICAL AND operations returns TRUE or 1.
3.4.2 Logical or The binary “or” operator returns the logical disjunction of its two operands. The condition becomes true if both the operands are true. It is the same as “||” but with a lower precedence.
The above pictorial helps you to understand the concept of LOGICAL OR operation with an analogy of taps and water. In case-1 of the picture, both of the taps are closed, so the water is not flowing down. Which explains that if both of conditions are FALSE or 0, the return is FALSE or 0. 84
Implementing Conditional Logic
In case-2 of the picture, one of the taps are closed, and we can see that the water is flowing down. Which explains that if any of conditions are TRUE or 1, the return is TRUE or 1. case-3 of the picture, resembles CASE -2. In case-4 of the picture, both of the taps are open, so the water is flowing down. Which explains that if both of conditions are TRUE or 1, the return is TRUE or 1. So we can conclude that in LOGICAL OR operation, if any of the conditions are true, the output is TRUE or 1.
3.4.3 Logical not The logical not or ! operator is used to reverse the logical state of its operand. If a condition is false, the logical not operator makes it true.
Example: Ruby logical operator puts (“logical operators in Ruby”) ruby = “x” programming = “y” if ruby == “foo” && programming == “bar” puts “&&” end if ruby == “foo” and programming == “bar” puts “&& and” end p, q, r, s = 1, 2 ,3 , 4 if p == 1 && q == 2 && r == 3 && s == 4 puts sum = p + q + r + s end
85
Basic Computer Coding: Ruby
programming = “ruby”
if ruby == “foo” || programming == “bar” puts “||” end
if ruby == “foo” or programming == “bar” puts “|| or” end
ruby = “awesome” if ruby == “foo” or programming == “bar” puts “|| or” else puts “sorry!” end
if not (ruby == “foo” || programming == “bar”) puts “nothing!” end
if !(ruby == “foo” or programming == “bar”) puts “nope!” 86
Implementing Conditional Logic
end Output: logical operators in Ruby 10 sorry! nothing! nope!
Example-1: Ruby operators (&&, and) precedence irb(main):016:0> foo = :foo => :foo irb(main):017:0> bar = nil => nil irb(main):018:0> x = foo and bar => nil irb(main):019:0> x => :foo irb(main):020:0> x = foo && bar => nil irb(main):021:0> x => nil irb(main):022:0> x = (foo and bar) => nil irb(main):023:0> x 87
Basic Computer Coding: Ruby
=> nil irb(main):024:0> (x = foo) && bar => nil irb(main):025:0> x => :foo Example-1: Ruby operators (||, or) precedence irb(main):001:0> foo = :foo => :foo irb(main):002:0> bar = nil => nil irb(main):003:0> x = foo or bar => :foo irb(main):004:0> x => :foo irb(main):005:0> x = foo || bar => :foo irb(main):006:0> x => :foo irb(main):007:0> x = (foo or bar) => :foo irb(main):008:0> x => :foo irb(main):009:0> (x = foo) || bar 88
Implementing Conditional Logic
=> :foo irb(main):010:0> x => :foo
3.5 TERNARY OPERATOR Ternary operator logic uses “(condition) ? (true return value): (false return value)” statements to shorten your if/else structures. It first evaluates an expression for a true or false value and then execute one of the two given statements depending upon the result of the evaluation. Here is the syntax: test-expression ? if-true-expression : if-false-expression Advantages of Ternary Logic: Makes coding simple if/else logic quicker Makes code shorter Makes maintaining code quicker, easier # Example-1 var = 5; var_is_greater_than_three = (var > 3 ? true : false); puts var_is_greater_than_three # Example-2 score= 50 result = score > 40 ? ‘Pass’ : ‘Fail’ puts result
# Example-3 score = 10; 89
Basic Computer Coding: Ruby
age = 22; puts “Taking into account your age and score, you are : “,(age > 10 ? (score < 80 ? ‘behind’ : ‘above average’) : (score < 50 ? ‘behind’ : ‘above average’));
# Example-4 score = 81 puts “Based on your score, you are a “, (score > 80 ? “genius” : “Not genius”)
Output: true Pass Taking into account your age and score, you are : behind Based on your score, you are a genius
90
Implementing Conditional Logic
SUMMARY ■
Conditional analysis is the evaluation of a piece of data, followed by a choice between different actions, only one of which is executed, depending on the result of the analysis. This might involve examining something, such as player input or the value of a randomly generated number.
■
The elsif keyword provides you with one or more intermediate options after the initial if, where you can test various statements.
■
Ruby’s case statement provides a way to express conditional logic in a succinct way. It is similar to using elsifs with colons, but you use case in place of if, and when in place of elsif.
■
A while loop executes the code it contains as long as its conditional statement remains true. The following piece of code initializes a counter i to 0 and sets up an array containing four elements called breeds (horse breeds).
■
The unless and until statements are similar to if and while, except they are executed while their conditionals are false, whereas if and while statements are executed while their conditionals are true.
■
In Ruby assignment operator is done using the equal operator “=”. This is applicable both for variables and objects, as strings, floats, and integers are actually objects in Ruby, you’re always assigning objects.
■
The binary “and” operator returns the logical conjunction of its two operands. The condition becomes true if both the operands are true. It is the same as “&&” but with a lower precedence.
■
The binary “or” operator returns the logical disjunction of its two operands. The condition becomes true if both the operands are true.
91
Basic Computer Coding: Ruby
KNOWLEDGE CHECK 1.
2.
What is the use of else statement? a.
When the if condition is false then the next else condition will get executed
b.
When the if condition is false then the elsif condition will get executed
c.
When the if condition is false and if else condition is true then only it will get executed
d.
None of the mentioned
Is the following syntax correct? if conditional code... elsif conditional code.. else code end
3.
a.
True
b.
False
What is the output of the given code? if 1>2 puts “false” else puts “True” a.
False
b.
True
c.
Syntax error
d.
None of the mentioned
92
Implementing Conditional Logic
4.
5.
The expression specified by the when clause is evaluated as the left operand. If no when clauses match, case executes the code of the else clause. a.
True
b.
False
What error does the if condition gives if not terminated with end statement? a.
Syntax error
b.
Unexpected end
c.
Expecting keyword end
d.
All of the mentioned
REVIEW QUESTIONS 1.
Why is case/when somewhat more convenient than if/ elsif/else?
2.
What is the ternary operator?
3.
What is a statement modifier?
4.
Why is upto or downto more convenient than a regular for loop?
5.
An unless statement is the negated form of what other control structure?
6.
What are the synonyms for && and ||?
Check Your Result 1. (c)
2. (a)
3. (c)
93
4. (a)
5. (d)
Basic Computer Coding: Ruby
REFERENCES 1.
Gustavo Frederico Temple Pedrosa, Vitor de Lima, Leonardo Bianconi (2014). “Specifying MACRO for increase performance in ppc64”. Retrieved 12 July 2016.
2.
http://people.cs.pitt.edu/~xujie/cs447/Mips/cond.html
3.
http://ruby-for-beginners.rubymonstas.org/conditionals. html
4.
https://code.tutsplus.com/articles/ruby-for-newbiesconditional-statements-and-loops--net-16537
5.
https://launchschool.com/books/ruby/read/flow_control
6.
https://stackoverflow.com/questions/1962724/properusage-of-ruby-statement-modifiers
7.
https://stackoverflow.com/questions/35580916/howexactly-should-i-implement-conditional-logic-in-djangoforms
8.
https://stackoverflow.com/questions/4252936/how-do-iuse-the-conditional-operator-in-ruby
9.
https://www.formstack.com/blog/2016/spotlight-onconditional-logic/
10.
https://www.gravityforms.com/form-conditional-logic/
11.
https://www.tutorialspoint.com/ruby/ruby_if_else.htm
12.
Semantic Versioning starting with Ruby 2.1.0. December 21, 2013. Retrieved December 27, 2013.
13.
Endoh, Yusuke. (2013-02-24) Ruby 2.0.0-p0 is released. Ruby-lang.org. Retrieved on 2013-07-17.
14.
usa (2016-02-24). “Support plans for Ruby 2.0.0 and Ruby 2.1”. Ruby-lang.org. Retrieved 2017-04-18.
94
CHAPTER 4
WORKING WITH LOOPS “This is one of the reasons Lisp doesn’t get anywhere. The trend to promote features so clever that you stop thinking about your problem and start thinking about the clever features. CL’s loop is so powerful that people invented functional programming so that they’d never have to use it” ―G_Morgan in reddit
Learning Objectives After studying this chapter, you will be able to: ■
Explain a simple loop and controlling loop execution
■
Understanding the while loops and until loops
■
Discuss the do/while loops and for loops
■
Define the conditionals within loops and iterators
■
Explain the recursion and ruby flip-flop
Basic Computer Coding: Ruby
INTRODUCTION Loops in Ruby are used to execute the same block of code a specified number of times. For instance, you want to print a string ten times. You can type ten print statement, but it is easier to use a loop. The only thing you have to do is to setup a loop to execute the same block of code a specified number of times. Here we have discussed the loop statements supported by Ruby.
4.1 A Simple Loop The simplest way to create a loop in Ruby is using the loop method. looptakes a block, which is denoted by { ... } or do ... end. A loop will execute any code within the block (again, that’s just between the {} or do ... end) until you manually intervene with Ctrl + c or insert a break statement inside the block, which will force the loop to stop and the execution will continue after the loop. Let’s try an example of a loop by creating a file named loop_example. rb # loop_example.rb loop do puts “This will keep printing until you hit Ctrl + c” end Now we can run ruby loop_example.rb on the terminal and see what happens. You’ll notice the same statement keeps printing on the terminal. You’ll have to interrupt with a Ctrl + c to stop it. This will keep printing until you hit Ctrl + c This will keep printing until you hit Ctrl + c This will keep printing until you hit Ctrl + c This will keep printing until you hit Ctrl + c This will keep printing until you hit Ctrl + cInterrupt: from (pry):2:in `puts’ [2] pry(main)> 96
Working with loops
4.2 Controlling Loop Execution You’ll hardly do something like this in a real program as it’s not very useful and will result in an infinite loop. Eventually your system will crash. Let’s look at a more useful example with the break keyword by creating a file named useful_ loop.rb: # useful_loop.rb
Infinite loop is a sequence of instructions in a computer program which loops endlessly, either due to the loop having no terminating condition, having one that can never be met, or one that causes the loop to start over.
i=0 loop do i += 1 puts i break loop
# this will cause execution to exit the
end When you run useful_loop.rb in your terminal, the output should be: $ ruby useful_loop.rb 1 The break keyword allows us to exit a loop at any point, so any code after a break will not be executed. Next, let’s look at adding conditions within a loop by printing all even numbers from 0 up to 10. Let’s create a file named conditional_loop.rb # conditional_loop.rb
97
Remember That break will not exit the program, but only exit the loop and execution will continue on from after the loop.
Basic Computer Coding: Ruby
i=0 loop do i += 2 puts i if i == 10 break
# this will cause execution to exit the loop
end end Here’s the output when we run the file: $ ruby conditional_loop.rb 2 4 6 8 10 You can see from the above that break was not executed during the first 4 iterations through the loop, but on the 5th iteration, the if statement evaluated to true and so the code within the if statement was executed, which is just break, and execution exited the loop. We’ll talk explicitly about using conditionals within a loop later. Similar to how we use break to exit a loop, we can use the keyword next to skip the rest of the current iteration and start executing the next iteration. We’ll use the same example as before to demonstrate. This time we’ll skip 4. # next_loop.rb
i=0 loop do i += 2 if i == 4 next
# skip rest of the code in this iteration 98
Working with loops
end puts i if i == 10 break end end And here’s the output when we run the file. $ ruby next_loop.rb 2 6 8 10 Notice that the above code did not print out 4, because that was skipped over. Execution continued to the next iteration of the loop. break and next are important loop control concepts that can be used with loop or any other loop construct in Ruby, which we’ll cover one by one below. When combined with conditionals, you can start to build simple programs with interesting behavior.
4.3 WHILE LOOPS A while loop is given a parameter that evaluates to a boolean (remember, that’s just true or false). Once that boolean expression becomes false, the while loop is not executed again, and the program continues after the while loop. Code within the while loop can contain any kind of logic that you would like to perform. Let’s try an example of a while loop by creating a file named countdown.rb. We want this program to countdown from any number given by the user and print to the screen each number as it counts. Here we go! # countdown.rb 99
Basic Computer Coding: Ruby
x = gets.chomp.to_i
while x >= 0 puts x x=x-1 end
puts “Done!” Now go to your terminal and run this program with ruby countdown.rb. You’ll notice that the program initially waits for you to put in a number then executes the loop. Negative Number is a real number that is less than zero.
Initially the program evaluates the line x >= 0. This evaluates to true (unless you entered a negative number) and so the program enters the loop, executing puts x and the line after that, x = x - 1. Then the program returns to the top, now with the newly updated value of x and evaluates the x >= 0 again. This process repeats until the value of x is no longer greater than or equal to 0. It then exits the loop and continues with the rest of the program. You can see why it’s called a loop. It loops over the logic within itself repeatedly. We’d also like to take this opportunity to show you a small trick for refactoring this loop. # countdown.rb x = gets.chomp.to_i
100
Working with loops
while x >= 0 puts x x -= 1 # = 0 expression as the test to see if we should execute the loop, the code within the loop must modify the variable x in some way. If it does not, then x >= 0 will always evaluate to true and cause an infinite loop. If you ever find your program unresponsive, it’s possible that it is stuck in an infinite loop.
Example: The following codes print the numbers 0 through 10. The condition a < 10 is checked before the loop is entered, then the body executes, then the condition is checked again. When the condition results in false the loop is terminated. x= 1 y = 11 while x < y do print x ,”. Ruby while loop.\n” x +=1 end Copy Output:
101
Basic Computer Coding: Ruby
1. Ruby while loop. 2. Ruby while loop. 3. Ruby while loop. 4. Ruby while loop. 5. Ruby while loop. 6. Ruby while loop. 7. Ruby while loop. 8. Ruby while loop. 9. Ruby while loop. 10. Ruby while loop. Very early computers, such as Colossus, were programmed without the help of a stored program, by modifying their circuitry or setting banks of physical controls.
Within the while statement, the ‘do’ keyword is optional. The following loop is equivalent to the loop above: x= 1 y = 11 while x < y print x ,”. Ruby while loop.\n” x +=1 end Copy
Ruby while modifier: Like if and unless, while can be used as modifiers. x=0 102
Working with loops
x += 1 while x < 10 p x
# prints 10
Copy You can use begin and end to create a while loop that runs the body once before the condition:
x=0 begin x += 1 end while x 11 is checked when entering the loop and each time the loop body executes. If the condition is false the loop will continue to execute. x = 1 y = 11 until x > y do print x ,”. Ruby while loop.\n” x +=1 end Copy Output: 1. Ruby while loop. 2. Ruby while loop. 3. Ruby while loop. 4. Ruby while loop. 5. Ruby while loop. 6. Ruby while loop. 7. Ruby while loop. 8. Ruby while loop. 9. Ruby while loop. 10. Ruby while loop.
4.5 DO/WHILE LOOPS A do/while loop works in a similar way to a while loop; one important difference is that the code within the loop gets executed one time, prior to the conditional check to see if the code should 104
Working with loops
be executed. In a “do/while” loop, the conditional check is placed at the end of the loop as opposed to the beginning. Let’s write some code that asks if the user wants to perform an action again, but keep prompting if the user enters ‘Y’. This is a classic use case for a “do/while”, because we want to repeatedly perform an action based on some condition, but we want the action to be executed at least one time no matter what. # perform_again.rb loop do puts “Do you want to do that again?” answer = gets.chomp if answer != ‘Y’ break end end Notice that we’re using a simple loop, except the condition to break out of the loop occurs at the end, therefore ensuring that the loop executes at least once. Try copying and pasting the above code into irb and playing around with it yourself. Compare this with a normal “while” loop. Side note: there’s also another construct in Ruby that supports “do/ while” loops, like this: begin puts “Do you want to do that again?” answer = gets.chomp end while answer == ‘Y’ While the above works, it’s not recommended by Matz, the creator of Ruby.
4.6 FOR LOOPS In Ruby, for loops are used to loop over a collection of elements. Unlike a while loop where if we’re not careful we can cause an infinite loop, for loops have a definite end since it’s looping over a finite number of elements. It begins with the for reserved word, followed by a variable, then the in reserved word, and then a collection of 105
Basic Computer Coding: Ruby
elements. We’ll show this using an array and a range. A range is a special type in Ruby that captures a range of elements. For example 1..3 is a range that captures the integers 1, 2, and 3. # countdown3.rb Array is a systematic arrangement of similar objects, usually in rows and columns.
x = gets.chomp.to_i for i in 1..x do puts i end puts “Done!” The odd thing about the for loop is that the loop returns the collection of elements after it executes, whereas the earlier while loop examples return nil. Let’s look at another example using an array instead of a range. # countdown4.rb x = [1, 2, 3, 4, 5] for i in x do puts i end puts “Done!” You can see there are a lot of ways to loop through a collection of elements using Ruby. Let’s talk about some more interesting ways you can use conditions to modify the behavior of your loops. Most Rubyists forsake for loops and prefer using iterators instead.
106
Working with loops
#!/usr/bin/ruby
$i = 0 $num = 5
until $i > $num do puts(“Inside the loop i = #$i” ) $i +=1; end
4.7 CONDITIONALS WITHIN LOOPS To make loops more effective and precise, we can add conditional flow control within them to alter their behavior. Let’s use an if statement in a while loop to demonstrate. # conditional_while_loop.rb x =0 while x end => :doubler irb(main):004:0> doubler(2) 4 => nil irb(main):005:0> doubler(4) 8 => nil irb(main):006:0> doubler(8) 16 => nil You can do this much more simply using recursion. Take a look at this version of the method: def doubler(start) puts start if start < 10 doubler(start * 2) end end This version of the method calls the doubler method again, passing it the doubled version of the value stored in the start variable. Once 111
Basic Computer Coding: Ruby
again, here is the declaration and use of the method using irb: irb(main):001:0> def doubler(start) irb(main):002:1>
puts start
irb(main):003:1>
if start < 10
irb(main):004:2>
doubler(start * 2)
irb(main):005:2> end irb(main):006:1> end => :doubler irb(main):007:0> doubler(2) 2 4 8 16 => nil Another Example We are using a method that uses recursion to calculate the nth number in the fibonacci sequence. You can learn more about the fibonacci sequence here. Basically, it is a sequence of numbers in which each number is the sum of the previous two numbers in the sequence. Note: This example may take a few reads to really grasp what’s happening at every point in the program. That’s normal. Just take your time, and you’ll be fine. Also, be excited! We are getting closer to reading more real-world examples! Make the following file: # fibonacci.rb def fibonacci(number) if number < 2 number else fibonacci(number - 1) + fibonacci(number - 2) 112
Working with loops
end end puts fibonacci(6) If you’re panicking, don’t be scared. Soon this will be simple to you. We just have to take it slow and understand everything that’s going on, line-by-line. Recursion is a tricky subject for all programmers, so don’t let this frustrate you any more than a healthy amount. When learning recursion, drawing diagrams can help. We can use a tree like structure to see what is happening. (We used fto abbreviate fibonacci to save space.)
Each time the code branches off again you are calling the fibonacci function from within itself two times. If you take all of those ones and zeros and add them together, you’ll get the same answer you get when you run the code. You can see why computer programs are handy now. Think if you had to draw that diagram out every time you wanted to know the fibonacci respresentation of a number. Yikes! The key concept with recursion is that there is some baseline condition that returns a value, which then “unwinds” the recursive calls. You can think of the successive recursive calls building up, until some value is returned, and only then can the recursive calls be evaluated.
113
Basic Computer Coding: Ruby
4.10 Ruby Flip-Flop The flip-flop is used to process text from ruby one-line programs used with ruby -n or ruby -p. The form of the flip-flop is an expression that indicates when the flip-flop turns on, .. (or ...), then an expression that indicates when the flip-flop will turn off. While the flip-flop is on it will continue to evaluate to true, and false when off. The flip-flop must be used inside a conditional such as if, while, unless, until etc.
Example In the following example, the on condition is n==12. The flip-flop is initially off (false) for 10 and 11, but becomes on (true) for 12 and remains on through 18. After 18 it turns off and remains off for 19 and 20. selected = [] 10.upto 20 do |value| selected 5 str =~ pattern # => 5 You can also create regular expression objects by calling the Regexp class’s new method or by using the %r{...} syntax. The %r syntax is particularly useful when creating patterns that contain forward slashes: /mm\/dd/ # => /mm\/dd/ Regexp.new(“mm/dd”) # => /mm\/dd/ %r{mm/dd} # => /mm\/dd/
129
Remember Regular expression is a special text string for describing a search pattern. You can think of regular expressions as wildcards on steroids. You are probably familiar with wildcard notations such as *.txt to find all text files in a file manager. The regex equivalent is .*\.txt.
Basic Computer Coding: Ruby
5.2.1 Regular Expression Options A regular expression may include one or more options that modify the way the pattern matches strings. If you’re using literals to create the Regexp object, then the options are one or more characters placed immediately after the terminator. If you’re using Regexp.new, the options are constants used as the second parameter of the constructor. i
Case insensitive. The pattern match will ignore the case of letters in the pattern and string. (The old technique of setting $= to make matches case insensitive no longer works.)
o
Substitute once. Any #{...} substitutions in a particular regular expression literal will be performed just once, the first time it is evaluated. Otherwise, the substitutions will be performed every time the literal generates a Regexp object.
m
Multiline mode. Normally, “.” matches any character except a newline. With the /m option, “.” matches any character.
x
Extended mode. Complex regular expressions can be difficult to read. The x option allows you to insert spaces and newlines in the pattern to make it more readable. You can also use # to introduce comments.
Remember Another set of options allows you to set the language encoding of the regular expression. If none of these options is specified, the regular expression will have USASCII encoding if it contains only 7-bit characters. Otherwise, it will use the default encoding of the source file containing the literal: n: no encoding (ASCII), e: EUC, s: SJIS, and u: UTF-8.
Matching Against Patterns Once you have a regular expression object, 130
Working with Regular Expressions
you can match it against a string using the (Regexp#match(string) method or the match operators =~ (positive match) and !~ (negative match). The match operators are defined for both String and Regexp objects. One operand of the match operator must be a regular expression
The match operators return the character position at which the match occurred, while the match method returns a MatchData object. In all forms, if the match fails, nil is returned. After a successful match, Ruby sets a whole bunch of magic variables. $& receives the part of the string that was matched by the pattern, $‘ receives the part of the string that preceded the match, and $’ receives the string after the match. However, these particular variables are considered to be fairly ugly, so most Ruby programmers instead use the MatchData object returned from the match method, because it encapsulates all the information Ruby knows about the match.
Given a MatchData object, you can call pre_ match to return the part of the string before the match, post_match for the string after the match, and index using [0] to get the matched portion. We can use these methods to write a method, show_regexp, that illustrates where a particular pattern matches: def show_regexp(string, pattern) match = pattern.match(string) if match 131
Basic Computer Coding: Ruby
“#{match.pre_match}->#{match[0]} very in->t F->a Fats Wa->lle no match
5.2.2 Deeper Patterns We said earlier that, within a pattern, all characters match themselves except ., |, (, ), [, ], {, }, +, \, ^, $, *, and ?. Let’s dig a bit deeper into this. First, always remember that you need to escape any of these characters with a backslash if you want them to be treated as regular characters to match: show_regexp(‘yes | no’, /\|/) # => yes ->| yes ->(no) are you sur->e? Pr->i Price-> Price ->$ see [The Pick->A s->e see [The PickAxe-page ->1 see [The PickAxe-page ->12 P->r Price-> Pric->e Pr->i Price $->1 Price-> Price-> Pr->i see [The PickAxe-page 123->] see [The PickAxe-page ->1 see [The PickAxe->- It-> It costs $->1 “*o* i* **e *i*e” The \p construct is new with Ruby 1.9. It gives you an encodingaware way of matching a 1.9 character with a particular Unicode property: # encoding: utf-8 string = “∂y/∂x = 2πx” show_regexp(string, /\p{Alnum}/) # => ∂->y ∂y/∂x = ->2 ∂y/∂x-> ∂y/∂x = 2->π ->∂ It ->cos ->I It costs $12->. ->The The-> moon is made of The-> moon The m->oo The ->moo The ->mo -> ->”.
2
// Non-greedy: matches “perl>”.
140
“”
in
Working with Regular Expressions
5.2.7 Grouping with Parentheses You can use parentheses to group terms within a regular expression. Everything within the group is treated as a single regular expression # This matches an ‘a’ followed by one or more ‘n’s show_regexp(‘banana’, /an+/) # => b->an b->anan ->red ->red ball ->red ball ->red no match a = ‘the red angry sky’ show_regexp(a, /red (ball|angry) sky/) # => the ->red angry sky 0 “Hour is #$1, minute #$2” # => “Hour is 12, minute 50” /((\d\d):(\d\d))(..)/ =~ “12:50am” # => 0 “Time is #$1” # => “Time is 12:50” “Hour is #$2, minute #$3” # => “Hour is 12, minute 50” “AM/PM is #$4” # => “AM/PM is am” If you’re using the MatchData object returned by the match method, you can index into it to get the corresponding subpatterns: md = /(\d\d):(\d\d)(..)/.match(“12:50am”) “Hour is #{md[1]}, minute #{md[2]}” # => “Hour is 12, minute 50” md = /((\d\d):(\d\d))(..)/.match(“12:50am”) “Time is #{md[1]}” # => “Time is 12:50” “Hour is #{md[2]}, minute #{md[3]}” # => “Hour is 12, minute 50” “AM/PM is #{md[4]}” # => “AM/PM is am” The ability to use part of the current match later in that match allows you to look for various forms of repetition: # match duplicated letter show_regexp(‘He said “Hello”’, /(\w)\1/) # => He said “He>ll M->ississ He said “He>ll M->ississ 0 “Hour is #{hour}, minute #{min}” # => “Hour is 12, minute 50” Once you use named matches in a particular regular expression, Ruby no longer bothers to capture unnamed groups.
5.2.8 Alternatives We know that the vertical bar is special, because our line-splitting pattern had to escape it with a backslash. That’s because an unescaped vertical bar, as in |, matches either the construct that precedes it or the construct that follows it: a = “red ball blue sky” show_regexp(a, /d|e/) # => r->e red b->al ->red ball this is\n->the this ->is ->this no match Similarly, the patterns \b and \B match word boundaries and nonword boundaries, respectively. Word characters are ASCII letters, numbers, and underscores: show_regexp(“this is\nthe time”, /\bis/) # => this ->is th->is “q*ick brown fox” a.gsub(/[aeiou]/, ‘*’) # => “q**ck br*wn f*x” a.sub(/\s\S+/, ‘’) # => “quick fox” a.gsub(/\s\S+/, ‘’) # => “quick” The substitution methods can take a string or a block. If a block is used, it is passed the matching substring, and the block’s value is substituted into the original string. a = “quick brown fox” a.sub(/^./) {|match| match.upcase } # => “Quick brown fox” a.gsub(/[aeiou]/) {|vowel| vowel.upcase } # => “qUIck brOwn fOx” Iteration is the act of repeating a process, to generate a sequence of outcomes, with the aim of approaching a desired goal, target or result.
Maybe we want to normalize names entered by users into a web application. They may enter DAVE THOMAS, dave thomas, or dAvE tHoMas, and we’d like to store it as Dave Thomas. The following method is a simple first iteration. The pattern that matches the first character of a word is \b\w—look for a word boundary followed by a word character. Combine this with gsub, and we can hack the names: def mixed_case(name) name.downcase.gsub(/\b\w/) first.upcase }
{|first|
end mixed_case(“DAVE THOMAS”) # => “Dave Thomas” 146
Working with Regular Expressions
mixed_case(“dave thomas”) # => “Dave Thomas” mixed_case(“dAvE tHoMas”) # => “Dave Thomas” There’s an idiomatic way to write the substitution in Ruby, the symbol to_proc Trick, why it works def mixed_case(name) name.downcase.gsub(/\b\w/, &:upcase) end mixed_case(“dAvE tHoMas”) # => “Dave Thomas” You can also give sub and gsub a hash as the replacement parameter, in which case they will look up matched groups and use the corresponding values as replacement text: replacement = { “cat” => “feline”, “dog” => “canine” } replacement.default = “unknown” “cat and dog”.gsub(/\w+/, replacement) # => “feline unknown canine”
5.2.11 Backslash Sequences in the Substitution Earlier we noted that the sequences \1, \2, and so on, are available in the pattern, standing for the nth group matched so far. The same sequences can be used in the second argument of sub and gsub. puts “fred:smith”.sub(/(\w+):(\w+)/, ‘\2, \1’) puts “nercpyitno”.gsub(/(.)(.)/, ‘\2\1’) produces: smith, fred encryption You can also reference named groups: puts “fred:smith”.sub(/(?\w+):(?\w+)/, ‘\k, \ k’) 147
Basic Computer Coding: Ruby
puts “nercpyitno”.gsub(/(?.)(?.)/, ‘\k\k’) produces: smith, fred encryption Additional backslash sequences work in substitution strings: \& (last match), \+ (last matched group), \‘ (string prior to match), \’ (string after match), and \\ (a literal backslash). It gets confusing if you want to include a literal backslash in a substitution. The obvious thing is to write this: str.gsub(/\\/, ‘\\\\’) Ruby 1.9 was released on Christmas Day in 2007. Effective with Ruby 1.9.3, released October 31, 2011, Ruby switched from being dual-licensed under the Ruby License and the GPL to being duallicensed under the Ruby License and the two-clause BSD license. Adoption of 1.9 was slowed by changes from 1.8 that required many popular third party gems to be rewritten.
Clearly, this code is trying to replace each backslash in str with two. The programmer doubled up the backslashes in the replacement text, knowing that they’d be converted to \\ in syntax analysis. However, when the substitution occurs, the regular expression engine performs another pass through the string, converting \\ to \, so the net effect is to replace each single backslash with another single backslash. You need to write gsub(/\\/, ’\\\\\\\\\’)! str = ‘a\b\c’ # => “a\b\c” str.gsub(/\\/, ‘\\\\\\\\’) # => “a\\ b\\c” However, using the fact that \& is replaced by the matched string, you could also write this: str = ‘a\b\c’ # => “a\b\c” str.gsub(/\\/, ‘\&\&’) # => “a\\b\\c” If you use the block form of gsub, the string for substitution is analyzed only once (during the 148
Working with Regular Expressions
syntax pass), and the result is what you intended: str = ‘a\b\c’ # => “a\b\c” str.gsub(/\\/) { ‘\\\\’ } # => “a\\b\\c”
149
Basic Computer Coding: Ruby
SUMMARY ■
A regular expression is a pattern that can be matched against a string. It can be a simple pattern, such as the string must contain the sequence of letters “cat”, or the pattern can be complex, such as the string must start with a protocol identifier, followed by two literal forward slashes, followed by..., and so on.
■
A regular expression is a special sequence of characters that helps you match or find other strings or sets of strings using a specialized syntax held in a pattern.
■
Regular expression literals may include an optional modifier to control various aspects of matching. The modifier is specified after the second slash character
■
Pattern literals are like double-quoted strings. In particular, you can use #{...} expression substitutions in the pattern.
■
The sub method takes a pattern and some replacement text. If it finds a match for the pattern in the string, it replaces the matched substring with the replacement text.
■
A regular expression may include one or more options that modify the way the pattern matches strings. If you’re using literals to create the Regexp object, then the options are one or more characters placed immediately after the terminator.
■
These repetition constructs have a high precedence—they bind only to the immediately preceding matching construct in the pattern. /ab+/ matches an a followed by one or more b’s, not a sequence of ab’s.
■
Parentheses also collect the results of pattern matching. Ruby counts opening parentheses and for each stores the result of the partial match between it and the corresponding closing parenthesis.
■
It needs to specify match position. By default, a regular expression will try to find the first match for the pattern in a string. Match /iss/ against the string “Mississippi,” and it will find the substring “iss” starting at position 1 (the second character in the string).
150
Working with Regular Expressions
KNOWLEDGE CHECK 1.
2.
3.
Regular expressions are used to represent which language a.
Recursive language
b.
Context free language
c.
Regular language
d.
All of these
Which of the following operation can be applied on regular expressions? a.
Union
b.
Concatenation
c.
Closure
d.
All of these
Which of the following identity is wrong? a.
R+R=R
b.
(R*)* = R*
c.
ɛR = Rɛ = R
d. 4.
5.
ØR = RØ = RR*
Which of the following statement is true? a.
Every language that is defined by regular expression can also be defined by finite automata
b.
Every language defined by finite automata can also be defined by regular expression
c.
We can convert regular expressions into finite automata
d.
All of these
L is a regular Language if and only If the set of __________ classes of IL is finite. a.
Equivalence
b.
Reflexive
c.
Myhill
d.
Nerode 151
Basic Computer Coding: Ruby
REVIEW QUESTIONS 1.
Discuss about the regular-expression modifiers.
2.
What is regular-expression patterns?
3.
Define the regular expression options.
4.
Discuss on the role of character classes.
5.
What do you understand by the special character classes?
6.
How to grouping with parentheses in ruby?
7.
Determine the pattern-based substitution.
Check Your Result 1. (c)
2. (d)
3. (d)
152
4. (d)
5. (a)
Working with Regular Expressions
REFERENCES 1.
https://www.tutorialspoint.com/ruby/ruby_regular_ expressions.htm
2.
https://dgrisham.github.io/slides/ruby/3-regex/slides.pdf
3.
https://www.princeton.edu/~mlovett/reference/RegularExpressions.pdf
4.
https://media.pragprog.com/titles/ruby3/ruby3_extract_ regular_expressions.pdf
5.
https://www.geos.ed.ac.uk/~bmg/software/Perl%20Books/ RegExp_perl_python_java_etc.pdf
6.
https://bitcetera.com/page_attachments/0000/0030/regex_ in_a_nutshell.pdf
7.
http://web.cse.ohio-state.edu/~joseph.97/courses/3901/ lectures/lecture09.pdf
8.
https://doc.lagout.org/programmation/Regular%20 Expressions/Regular%20Expressions%20Cookbook_%20 Detailed%20Solutions%20in%20Eight%20 Programming%20Languages%20%282nd%20ed.%29%20 %5BGoyvaerts%20%26%20Levithan%202012-09-06%5D. pdf
9.
http://www.rubyguides.com/2015/06/ruby-regex/
153
CHAPTER 6
RUBY: OBJECT-ORIENTED PROGRAMMING “This is great stuff! Your descriptions are so vibrant and vivid that I’m rediscovering the truth buried in OO principles that are otherwise so internalized that I forget to explore them. Your thoughts on design and knowing the future are especially eloquent.” ―Ian McFarland
Learning Objectives After studying this chapter, you will be able to: ■
Focus on ruby class
■
Discuss about class inheritance
Basic Computer Coding: Ruby
INTRODUCTION Ruby is a pure object-oriented language and everything appears to Ruby as an object. Every value in Ruby is an object, even the most primitive things: strings, numbers and even true and false. Even a class itself is an object that is an instance of the Class class. This chapter will take you through all the major functionalities related to Object Oriented Ruby. A class is used to specify the form of an object and it combines data representation and methods for manipulating that data into one neat package. The data and methods within a class are called members of the class.
6.1 DEFINITION OF RUBY CLASS When you define a class, you define a blueprint for a data type. This doesn’t actually define any data, but it does define what the class name means, that is, what an object of the class will consist of and what operations can be performed on such an object. A class definition starts with the keyword class followed by the class name and is delimited with an end. For example, we defined the Box class using the keyword class as follows − class Box code end 156
Ruby: Object-Oriented Programming
The name must begin with a capital letter and by convention names that contain more than one word are run together with each word capitalized and no separating characters (CamelCase).
6.1.1 Define Ruby Objects A class provides the blueprints for objects, so basically an object is created from a class. We declare objects of a class using new keyword. Following statements declare two objects of class Box − box1 = Box.new box2 = Box.new
157
Basic Computer Coding: Ruby
The initialize Method A constructor is a special method that is used to initialize a newly created object and is called just after the memory is allocated for the object.
The initialize method is a standard Ruby class method and works almost same way as constructor works in other object oriented programming languages. The initialize method is useful when you want to initialize some class variables at the time of object creation. This method may take a list of parameters and like any other ruby method it would be preceded by def keyword as shown below − class Box def initialize(w,h) @width, @height = w, h end end
The instance Variables The instance variables are kind of class attributes and they become properties of objects once objects are created using the class. Every object›s attributes are assigned individually and share no value with other objects. They are accessed using the @ operator within the class but to access them outside of the class we use public 158
Ruby: Object-Oriented Programming
methods, which are called accessor methods. If we take the above defined class Box then @width and @height are instance variables for the class Box. class Box def initialize(w,h) # assign instance variables @width, @height = w, h end end
6.1.2 The accessor & setter Methods To make the variables available from outside the class, they must be defined within accessor methods, these accessor methods are also known as a getter methods. Following example shows the usage of accessor methods − #!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # accessor methods def printWidth @width end
159
Basic Computer Coding: Ruby
def printHeight @height end end # create an object box = Box.new(10, 20) # use accessor methods x = box.printWidth() y = box.printHeight() puts “Width of the box is : #{x}” puts “Height of the box is : #{y}” When the above code is executed, it produces the following result − Width of the box is : 10 Height of the box is: 20 Similar to accessor methods, which are used to access the value of the variables, Ruby provides a way to set the values of those variables from outside of the class using setter methods, which are defined as below #!/usr/bin/ruby -w
160
Ruby: Object-Oriented Programming
# define a class class Box
Provide public setter and getter methods to modify and view the variables values.
# constructor method def initialize(w,h) @width, @height = w, h end
# accessor methods def getWidth @width end def getHeight @height end
# setter methods def setWidth=(value) @width = value end def setHeight=(value) @height = value end 161
Basic Computer Coding: Ruby
end
# create an object box = Box.new(10, 20)
# use setter methods box.setWidth = 30 box.setHeight = 50
# use accessor methods x = box.getWidth() y = box.getHeight()
puts “Width of the box is : #{x}” puts “Height of the box is : #{y}” When the above code is executed, it produces the following result − Width of the box is : 30 Height of the box is : 50
The instance Methods The instance methods are also defined in the same way as we define any other method using def keyword and they can be used using a class instance only as shown below. Their functionality is not limited to access the instance variables, but also they can do a lot more as per your requirement. #!/usr/bin/ruby -w 162
Ruby: Object-Oriented Programming
# define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end
# create an object box = Box.new(10, 20)
# call instance methods a = box.getArea() puts “Area of the box is : #{a}” When the above code is executed, it produces the following result − Area of the box is : 200
163
Basic Computer Coding: Ruby
6.1.3 The class Methods and Variables A delimiter is a sequence of one or more characters used to specify the boundary between separate, independent regions in plain text or other data streams.
The class variables is a variable, which is shared between all instances of a class. In other words, there is one instance of the variable and it is accessed by object instances. Class variables are prefixed with two @ characters (@@). A class variable must be initialized within the class definition as shown below. A class method is defined using def self.methodname(), which ends with end delimiter and would be called using the class name as classname.methodname as shown in the following example − #!/usr/bin/ruby -w
class Box # Initialize our class variables @@count = 0 def initialize(w,h) # assign instance avriables @width, @height = w, h
164
Ruby: Object-Oriented Programming
@@count += 1 end
def self.printCount() puts “Box count is : #@@count” In 2001, Laing and Coleman examined several NASA Goddard Space Flight Center applications (rocket science) with the express intention of finding “a way to produce cheaper and higher quality software.”
end end
# create two object box1 = Box.new(10, 20) box2 = Box.new(30, 100)
# call class method to print box count Box.printCount() When the above code is executed, it produces the following result − Box count is: 2
6.1.4 The to_s Method Any class you define should have a to_s instance method to return a string representation of the object. Following is a simple example to represent a Box object in terms of width and height − #!/usr/bin/ruby -w
165
Basic Computer Coding: Ruby
class Box # constructor method def initialize(w,h) @width, @height = w, h end # define to_s method def to_s “(w:#@width,h:#@height)” # string formatting of the object. end end # create an object box = Box.new(10, 20) # to_s method will be called in reference of string automatically. puts “String representation of box is : #{box}” When the above code is executed, it produces the following result − String representation of box is: (w:10,h: 20)
166
Ruby: Object-Oriented Programming
6.1.5 Access Control Ruby gives you three levels of protection at instance methods level, which may be public, private, or protected. Ruby does not apply any access control over instance and class variables. ■
Public Methods: Public methods can be called by anyone. Methods are public by default except for initialize, which is always private.
■
Private Methods: Private methods cannot be accessed, or even viewed from outside the class. Only the class methods can access private members.
■
Protected Methods: A protected method can be invoked only by objects of the defining class and its subclasses. Access is kept within the family.
Following is a simple example to show the syntax of all the three access modifiers − #!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # instance method by default it is public def getArea getWidth() * getHeight end 167
Remember If Agile is correct, two other things are also true. First, there is absolutely no point in doing a Big Up Front Design (BUFD) (because it cannot possibly be correct), and second, no one can predict when the application will be done (because you don’t know in advance what it will eventually do).
Basic Computer Coding: Ruby
# define private accessor methods def getWidth @width end def getHeight @height end # make them private private :getWidth, :getHeight # instance method to print area def printArea @area = getWidth() * getHeight puts “Big box area is : #@area” end # make it protected protected :printArea end # create an object box = Box.new(10, 20) # call instance methods a = box.getArea() puts “Area of the box is : #{a}”
168
Ruby: Object-Oriented Programming
# try to call protected or methods box.printArea() When the above code is executed, it produces the following result. Here, first method is called successfully but second method gave a problem. Area of the box is : 200 test.rb:42: protected method `printArea’ called for #
(NoMethodError)
6.2 CLASS INHERITANCE One of the most important concepts in objectoriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application. Inheritance also provides an opportunity to reuse the code functionality and fast implementation time but unfortunately Ruby does not support multiple levels of inheritances but Ruby supports mixins. A mixin is like a specialized implementation of multiple inheritance in which only the interface portion is inherited. Ruby also supports the concept of sub classing, i.e., inheritance and following example explains the concept. The syntax for extending a class is simple. Just add a < character and the name of the superclass to your class statement. For example, following define a class BigBox as a subclass of Box −
169
When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class or superclass, and the new class is referred to as the derived class or sub-class.
Basic Computer Coding: Ruby
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # define a subclass class BigBox < Box
# add a new instance method def printArea 170
Ruby: Object-Oriented Programming
@area = @width * @height puts “Big box area is : #@area” end end
Overriding is a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes.
# create an object box = BigBox.new(10, 20)
# print the area box.printArea() When the above code is executed, it produces the following result − Big box area is: 200
6.2.1 Methods Overriding Though you can add new functionality in a derived class, but sometimes you would like to change the behavior of already defined method in a parent class. You can do so simply by keeping the method name same and overriding the functionality of the method as shown below in the example − #!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h 171
Basic Computer Coding: Ruby
end # instance method def getArea @width * @height end end # define a subclass class BigBox < Box # change existing getArea method as follows def getArea @area = @width * @height puts “Big box area is : #@area” end end # create an object box = BigBox.new(10, 20) # print the area using overriden method. box.getArea()
6.2.2 Operator Overloading We’d like the + operator to perform vector addition of two Box objects using +, the * operator to multiply a Box width and height by a scalar, and the unary - operator to do negate the width and height of the Box. Here is a version of the Box class with mathematical operators defined − class Box def initialize(w,h)
# Initialize the width and height
@width,@height = w, h 172
Ruby: Object-Oriented Programming
end def +(other)
# Define + to do vector addition
Box.new(@width + other.width, @height + other.height) end def -@
# Define unary minus to negate width and height
Box.new(-@width, -@height) end def *(scalar)
# To perform scalar multiplication
Box.new(@width*scalar, @height*scalar) end end
6.2.3 Freezing Objects Sometimes, we want to prevent an object from being changed. The freeze method in Object allows us to do this, effectively turning an object into a constant. Any object can be frozen by invoking Object. freeze. A frozen object may not be modified: you can’t change its instance variables. You can check if a given object is already frozen or not using Object.frozen?method, which returns true in case the object is frozen otherwise a false value is return. Following example clears the concept − 173
Basic Computer Coding: Ruby
#!/usr/bin/ruby -w # define a class class Box # constructor method def initialize(w,h) @width, @height = w, h end # accessor methods def getWidth @width end def getHeight @height end # setter methods def setWidth=(value) @width = value end def setHeight=(value) @height = value end end # create an object box = Box.new(10, 20) # let us freez this object box.freeze if( box.frozen? ) 174
Ruby: Object-Oriented Programming
puts “Box object is frozen object” else puts “Box object is normal object” end # now try using setter methods box.setWidth = 30 box.setHeight = 50 # use accessor methods x = box.getWidth() y = box.getHeight() puts “Width of the box is : #{x}” puts “Height of the box is : #{y}” When the above code is executed, it produces the following result − Box object is frozen object test.rb:20:in `setWidth=’: can’t modify frozen object (TypeError) from test.rb:39
6.2.4 Class Constants You can define a constant inside a class by assigning a direct numeric or string value to a variable, which is defined without using either @ or @@. By convention, we keep constant names in upper case. Once a constant is defined, you cannot change its value but you 175
Basic Computer Coding: Ruby
A convention, in the sense of a meeting, is a gathering of individuals who meet at an arranged place and time in order to discuss or engage in some common interest.
can access a constant directly inside a class much like a variable but if you want to access a constant outside of the class then you would have to use class name::constant as shown in the below example. #!/usr/bin/ruby -w # define a class class Box BOX_COMPANY = “TATA Inc” BOXWEIGHT = 10 # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # create an object box = Box.new(10, 20) # call instance methods a = box.getArea() puts “Area of the box is : #{a}” puts Box::BOX_COMPANY puts “Box weight is: #{Box::BOXWEIGHT}” When the above code is executed, it produces the following result − Area of the box is : 200 TATA Inc Box weight is: 10 176
Ruby: Object-Oriented Programming
Class constants are inherited and can be overridden like instance methods.
6.2.5 Create Object Using Allocate There may be a situation when you want to create an object without calling its constructor initialize i.e. using new method, in such case you can call allocate, which will create an uninitialized object for you as in the following example − #!/usr/bin/ruby -w # define a class class Box attr_accessor :width, :height # constructor method def initialize(w,h) @width, @height = w, h end # instance method def getArea @width * @height end end # create an object using new box1 = Box.new(10, 20) # create another object using allocate box2 = Box.allocate # call instance method using box1 a = box1.getArea() 177
Basic Computer Coding: Ruby
puts “Area of the box is : #{a}” # call instance method using box2 a = box2.getArea() puts “Area of the box is : #{a}” When the above code is executed, it produces the following result − Area of the box is : 200 test.rb:14: warning: instance variable @width not initialized test.rb:14: warning: instance variable @height not initialized test.rb:14:in `getArea’: undefined method `*’ for nil:NilClass (NoMethodError) from test.rb:29
6.2.6 Class Information If class definitions are executable code, this implies that they execute in the context of some object: self must reference something. Let’s find out what it is. #!/usr/bin/ruby -w class Box # print class information puts “Type of self = #{self.type}” puts “Name of self = #{self.name}” end 178
Ruby: Object-Oriented Programming
When the above code is executed, it produces the following result − Type of self = Class Name of self = Box This means that a class definition is executed with that class as the current object. This means that methods in the met class and its super classes will be available during the execution of the method definition.
179
Basic Computer Coding: Ruby
SUMMARY ■
Ruby is a pure object-oriented language and everything appears to Ruby as an object. Every value in Ruby is an object, even the most primitive things: strings, numbers and even true and false. Even a class itself is an object that is an instance of the Class class.
■
The initialize method is a standard Ruby class method and works almost same way as constructor works in other object oriented programming languages. The initialize method is useful when you want to initialize some class variables at the time of object creation.
■
The class variables is a variable, which is shared between all instances of a class. In other words, there is one instance of the variable and it is accessed by object instances.
■
One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application.
■
Sometimes, we want to prevent an object from being changed. The freeze method in Object allows us to do this, effectively turning an object into a constant. Any object can be frozen by invoking Object freeze. A frozen object may not be modified: you can’t change its instance variables.
180
Ruby: Object-Oriented Programming
KNOWLEDGE CHECK 1.
2.
3.
4.
5.
In a class, member variables are often called its _________, and its member functions are sometimes referred to as its behaviour, or ____________. a.
attributes, methods
b.
none of these
c.
values, morals
d.
data, activities
e.
attributes, activities
Which of these keywords are access specifiers? a.
near and far
b.
opened and closed
c.
table and row
d.
none of these
e.
private and public
True/False: An Object can be declared prior to the class definition. a.
True
b.
False
Use of __________ protects data from inadvertent modifications. a.
protect() member function
b.
private access specifier
c.
class protection operator, @
d.
none of these
e.
public access specifier
You can redefine the way _______ work when used with objects. a.
none of these
b.
white space characters
c.
standard operators 181
Basic Computer Coding: Ruby
d.
pre-processor directives
e.
undefined variables
REVIEW QUESTIONS 1.
Define Ruby Objects.
2.
Focus on class methods and variables in Ruby.
3.
Ruby does not apply any access control over instance and class variables, Explain.
4.
Discuss about freezing objects.
5.
How can Initialize method is a standard Ruby class method? Explain.
Check your Result 1. (a)
2. (e)
3. (b)
182
4. (b)
5. (c)
Ruby: Object-Oriented Programming
REFERENCES 1.
http://ptgmedia.pearsoncmg.com/images/9780321721334/ samplepages/0321721330.pdf
2.
http://ruby-for-beginners.rubymonstas.org/object_ oriented_programming.html
3.
http://zetcode.com/lang/rubytutorial/oop/
4.
https://dev.to/steff_br/object-oriented-programming-withruby-pt1--a6f
5.
https://launchschool.com/books/oo_ruby/read/the_object_ model
6.
https://medium.freecodecamp.org/an-introduction-toobject-oriented-programming-with-ruby-73531e2b8ddc
7.
https://mixandgo.com/learn/object-oriented-programmingoop-with-ruby
8.
https://people.engr.ncsu.edu/efg/517/f07/lectures/notes/ lec6.pdf
9.
https://www.tutorialspoint.com/ruby/ruby_database_ access.htm
183
CHAPTER 7
DEBUGGER “Debugging itu adalah sebuah metode yang dilakukan oleh para programmer untuk mencari jarum di tumpukan jerami” ―Harly Umboh
Learning Objectives After studying this chapter, you will be able to: ■
Explain the Ruby debugger
■
Understanding the logger
■
Discuss the debugging with the bye bug gem
Basic Computer Coding: Ruby
INTRODUCTION Debugging refers to a process in software development whereby program analysts comb through computer code looking for “bugs” — the source of errors, flaws or security holes in the internal program instructions. Hardware development also goes through debugging to ensure compatibility with current hardware standards and interoperability between components that adhere to the same protocols. Additionally, debugging guarantees that hardware and software is backward compatible, or will coexist with preexisting standards that might still be in use. Software debugging takes place in two phases. The first phase is known as “alpha testing,” and is performed in-house before the software is made public. The second phase is carried out through a public process known as “beta testing.” Beta testers are voluntary computer enthusiasts that use beta software at their own risks under agreement that errors or problems will be reported to developers. Since bugs must be isolated and identified before they can be patched, the first step is to test the software under various conditions. When a bug reveals itself, the debugger takes note of the exact conditions under which the bug appeared, including the current running function, operating system type and version, and other software or hardware components that might be relevant. Public beta testers submit detailed reports online listing pertinent details accordingly, typically by filling out a pre-designed form. Once both debugging phases are completed, the software program is ready for a general release as a stable version. However, debugging continues as a maintenance protocol for the life of the product, intensifying with major upgrades. Hardware is debugged before it reaches the market and does not undergo real-world beta testing per se, as this would be too expensive and problematic for a number of fairly obvious reasons. Instead, most hardware manufacturers provide an online interface where users can get technical support or report problems with hardware. In many cases these problems turn out to be user error, but the process also serves to reveal bugs that were not caught in the initial debugging phase. Debuggers can go back to the instructions encoded in the controlling chips and make changes to rid the 186
Debugger
hardware of the bugs. The manufacturer can then provide a firmware upgrade that users can download online to update their hardware. While in-house debugging can certainly rid software and hardware of many bugs, nothing replaces real-world testing. It is virtually impossible for an author or manufacturer to replicate every conceivable condition and system under which the hardware or software will be used. Many experienced IBM-PC users wait for a period of 12-36 months before migrating to a new operating system for this reason, such as making the switch from Windows™ XP™ to Windows Vista™. This gives the community time to identify any major security problems, bugs or other initial problems that might require debugging and patching.
7.1 RUBY – DEBUGGER It doesn’t matter how easy a language is to use, it usually contains some bugs if it is more than a few lines long. To help deal with bugs, the standard distribution of Ruby includes a debugger. In order to start the Ruby debugger, load the debug library using the command-line option -r debug. The debugger stops before the first line of executable code and asks for the input Command is a directive to a computer of user commands.
7.1.1 Usage Syntax Here is the usage syntax to use ruby debugger − $ ruby -r debug filename [, ...]
187
program acting as an interpreter of some kind to perform a specific task.
Basic Computer Coding: Ruby
7.1.2 Ruby Debugger Commands Here is a complete list of commands, which you can use while debugging your program. Here, it is not necessary to use complete keyword to give a command, part given inside [...] is option. Sr.No.
Command & Description
1
b[reak] [< file| class>:]< line| method> Sets breakpoint to some position. Breakpoint is a place where you want to pause program execution for debugging purpose.
2
wat[ch] expression Sets watchpoints.
3
cat[ch] (exception|off) Sets catchpoint to an exception.
4
b[reak] Displays breakpoints and watchpoints.
5
del[ete] [n] Deletes breakpoints.
6
disp[lay] expression Displays value of expression.
7
undisp[lay] [ n] Removes display of n
8
c[ont] Continues execution.
9
s[tep] [ n] Executes next n lines stepping into methods.
10
n[ext] [ n] Executes next n lines stepping over methods.
11
w[here] Displays stack frame
188
Debugger
12
f[rame] Synonym for where.
13
l[ist][] Displays source lines from n to m.
14
up [ n] Moves up n levels in the stack frame.
15
down [ n] Moves down n levels in the stack frame.
16
fin[ish] Finishes execution of the current method.
17
tr[ace] [on|off] Toggles trace mode on and off.
18
q[uit] Exits debugger.
19
v[ar] g[lobal] Displays global variables.
20
v[ar] l[ocal] Displays local variables.
21
v[ar] i[instance] object Displays instance variables of object
22
v[ar] c[onst] object Displays constants of object.
23
m[ethod] i[instance] object Displays instance methods of object.
24
m[ethod] class| module Displays instance methods of the class or module.
25
th[read] l[ist] Displays threads.
189
Basic Computer Coding: Ruby
26
th[read] c[ur[rent]] Displays current thread.
27
th[read] n Stops specified thread.
28
th[read] stop > Synonym for th[read] n.
29
th[read] c[ur[rent]] n> Synonym for th[read] n
30
th[read] resume > Resumes thread n
31
p expression Evaluates the expression
32
h[elp] Displays help message
33
everything else Evaluates.
Example Consider the following file hello.rb, which needs to be debugged − #!/usr/bin/env ruby class Hello def initialize( hello ) @hello = hello end def hello @hello end end salute = Hello.new( “Hello, Mac!” ) puts salute.hello Here is one interactive session captured. Given commands are 190
Debugger
written in bold − [root@ruby]# ruby -r debug hello.rb Debug.rb Emacs support available. hello.rb:3:class Hello (rdb:1) v l salute => nil (rdb:1) b 10 Set breakpoint 1 at hello.rb:10 (rdb:1) c Hello, Mac! [root@ruby]#
7.2 THE LOGGER It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment.
7.2.1 What is the Logger? Rails makes use of the ActiveSupport::Logger class to write log information. Other loggers, such as Log4r, may also be substituted. You can specify an alternative logger in config/application.rb or any other environment file, for example: config.logger = Logger.new(STDOUT) config.logger = Log4r::Logger.new(“Application Log”) Or in the Initializer section, add any of the following Rails.logger = Logger.new(STDOUT) Rails.logger = Log4r::Logger.new(“Application Log”) By default, each log is created under Rails.root/log/ and the log file is named after the environment in which the application is running.
191
Basic Computer Coding: Ruby
If your program makes use of a framework like Rails or Sinatra your stacktrace might be quite convoluted. It might be useful to filter the stack trace by your project name. puts caller.select { |line| line.include? ‘project_name’ } or puts caller.select { |line| line[‘project_name’] }
7.2.2 Log Levels When something is logged, it’s printed into the corresponding log if the log level of the message is equal to or higher than the configured log level. If you want to know the current log level, you can call the Rails.logger.level method. The available log levels are: :debug, :info, :warn, :error, :fatal, and :unknown, corresponding to the log level numbers from 0 up to 5, respectively. To change the default log level, use config.log_level = :warn # In any environment initializer, or Rails.logger.level = 0 # at any time This is useful when you want to log under development or staging without flooding your production log with unnecessary information. The default Rails log level is debug in all environments.
7.2.3 Sending Messages To write in the current log use the logger. (debug|info|warn|error|fatal) method from Controller is a chip, within a controller, model or mailer: an expansion card, or logger.debug “Person attributes hash: #{@ a stand-alone device that interfaces with a person.attributes.inspect}” peripheral device.
logger.info “Processing the request...” 192
Debugger
logger.fatal “Terminating application, raised unrecoverable error!!!” Here’s an example of a method instrumented with extra logging: class ArticlesController < ApplicationController # ... def create @article = Article.new(article_params) logger.debug “New article: #{@article.attributes.inspect}” logger.debug “Article should be valid: #{@article.valid?}” if @article.save logger.debug “The article was saved and now the user is going to be redirected...” redirect_to @article, notice: ‘Article was successfully created.’ else render :new end end # ... private def article_params params.require(:article).permit(:title, :body, :published) end end Here’s an example of the log generated when this controller action is executed: Started POST “/articles” for 127.0.0.1 at 2017-08-20 20:53:10 +0900 Processing by ArticlesController#create as HTML Parameters: {“utf8”=>”✓”, “authenticity_ token”=>”xhuIbSBFytHCE1agHgvrlKnSVIOGD6jltW2tO+P6a/ A C j Q 3 i g j p V 4 O d b s Z j I h C 9 8 Q i z W H 9 Yd K o k r q x B C J r t o q Q = = ” , “article”=>{“title”=>”Debugging Rails”, “body”=>”I’m learning how 193
Basic Computer Coding: Ruby
to print in logs!!!”, “published”=>”0”}, “commit”=>”Create Article”} New article: {“id”=>nil, “title”=>”Debugging Rails”, “body”=>”I’m learning how to print in logs!!!”, “published”=>false, “created_ at”=>nil, “updated_at”=>nil} Article should be valid: true (0.1ms) BEGIN SQL (0.4ms) INSERT INTO “articles” (“title”, “body”, “published”, “created_at”, “updated_at”) VALUES ($1, $2, $3, $4, $5) RETURNING “id” [[“title”, “Debugging Rails”], [“body”, “I’m learning how to print in logs!!!”], [“published”, “f”], [“created_at”, “2017-08-20 11:53:10.010435”], [“updated_at”, “2017-08-20 11:53:10.010435”]] (0.3ms) COMMIT The article was saved and now the user is going to be redirected... Redirected to http://localhost:3000/articles/1 Completed 302 Found in 4ms (ActiveRecord: 0.8ms) Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels to avoid filling your production logs with useless trivia.
7.2.4 Tagged Logging When running multi-user, multi-account applications, it’s often useful to be able to filter the logs using some custom rules. TaggedLogging in Active Support helps you do exactly that by stamping log lines with subdomains, request ids, and anything else to aid debugging such applications. logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT)) logger.tagged(“BCX”) { logger.info “Stuff” } Logs “[BCX] Stuff”
#
logger.tagged(“BCX”, “Jason”) { logger.info “Stuff” } Logs “[BCX] [Jason] Stuff”
#
logger.tagged(“BCX”) { logger.tagged(“Jason”) { logger.info “Stuff” } } # Logs “[BCX] [Jason] Stuff”
194
Debugger
7.2.5 Impact of Logs on Performance Logging will always have a small impact on the performance of your Rails app, particularly when logging to disk. Additionally, there are a few subtleties: Using the: debug level will have a greater performance penalty than: fatal, as a far greater number of strings are being evaluated and written to the log output (e.g. disk). Another potential pitfall is too many calls to Logger in your code: logger.debug “Person attributes hash: #{@ person.attributes.inspect}” In the example, there will be a performance impact even if the allowed output level doesn’t include debug. The reason is that Ruby has to evaluate these strings, which includes instantiating the somewhat heavy String object and interpolating the variables. Therefore, it’s recommended to pass blocks to the logger methods, as these are only evaluated if the output level is the same as — or included in — the allowed level (i.e. lazy loading). The same code rewritten would be: logger.debug {“Person attributes hash: #{@ person.attributes.inspect}”} The contents of the block, and therefore the string interpolation, are only evaluated if debug is enabled. This performance savings are only really noticeable with large amounts of logging, but it’s a good practice to employ.
195
Console is the text entry and display device for system administration messages, particularly those from the BIOS or boot loader, the kernel, from the init system and from the system logger.
Basic Computer Coding: Ruby
7.3 DEBUGGING WITH THE BYE BUG GEM When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem. Unfortunately, there are times when this sort of error tracking is not effective in finding the root cause of a problem. When you actually need to journey into your running source code, the debugger is your best companion.
7.3.1 Setup You can use the byebug gem to set breakpoints and step through live code in Rails. To install it, just run: $ gem install byebug Inside any Rails application you can then invoke the debugger by calling the byebug method. Here’s an example: class PeopleController < ApplicationController def new byebug @person = Person.new end end
7.3.2 The Shell As soon as your application calls the byebug method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at the debugger’s prompt (byebug). Before the prompt, the code around the line that is about to be run will be displayed and the current line will be marked by ‘=>’, like this: [1, 10] in /PathTo/project/app/controllers/articles_controller.rb 3: 4:
# GET /articles
5:
# GET /articles.json
6:
def index 196
Debugger
7: => 8:
byebug @articles = Article.find_recent
9: 10: 11: 12:
respond_to do |format| format.html # index.html.erb format.json { render json: @articles }
(byebug) If you got there by a browser request, the browser tab containing the request will be hung until the debugger has finished and the trace has finished processing the entire request.
For example => Booting Puma => Rails 5.1.0 application starting in development on http://0.0.0.0:3000 => Run `rails server -h` for more startup options Puma starting in single mode... * Version 3.4.0 (ruby 2.3.1-p112), codename: Owl Bowl Brawl * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://localhost:3000 Use Ctrl-C to stop Started GET “/” for 127.0.0.1 at 2014-04-11 13:11:48 +0200 HTML is the standard markup language for ActiveRecord::SchemaMigration Load creating web pages and (0.2ms) SELECT “schema_migrations”.* FROM web applications. “schema_migrations” Processing by ArticlesController#index as HTML [3, 12] in /PathTo/project/app/controllers/ articles_controller.rb 3: 197
Basic Computer Coding: Ruby
4: # GET /articles 5: # GET /articles.json 6: def index 7:
byebug
=> 8:
@articles = Article.find_recent
9: 10:
respond_to do |format|
11:
format.html # index.html.erb
12:
format.json { render json: @articles }
(byebug) Now it’s time to explore your application. A good place to start is by asking the debugger for help. Type: help (byebug) help break
-- Sets breakpoints in the source code
catch
-- Handles exception catchpoints
condition -- Sets conditions on breakpoints continue -- Runs until program ends, hits a breakpoint or reaches a line debug
-- Spawns a subdebugger
delete
-- Deletes breakpoints
disable
-- Disables breakpoints or displays
display
-- Evaluates expressions every time the debugger stops
down edit enable finish
-- Moves to a lower frame in the stack trace -- Edits source files -- Enables breakpoints or displays -- Runs the program until frame returns
frame
-- Moves to a frame in the call stack
help
-- Helps you using byebug
history
-- Shows byebug’s history of commands 198
Debugger
info -- Shows several informations about the program being debugged interrupt -- Interrupts the program irb
-- Starts an IRB session
kill
-- Sends a signal to the current process
list
-- Lists lines of source code
method
-- Shows methods of an object, class or module
next
-- Runs one or more lines of code
pry
-- Starts a Pry session
quit
-- Exits byebug
restart
-- Restarts the debugged program
save
-- Saves current byebug session to a file
set
-- Modifies byebug settings
show
-- Shows byebug settings
source
-- Restores a previously saved byebug session
step
-- Steps into blocks or methods one or more times
thread
-- Commands to manipulate threads
tracevar
-- Enables tracing of a global variable
undisplay -- Stops displaying all or some expressions when program stops untracevar -- Stops tracing a global variable up
-- Moves to a higher frame in the stack trace
var
-- Shows variables and its values
where
-- Displays the backtrace
(byebug) To see the previous ten lines you should type list- (or l-). (byebug) l[1, 10] in /PathTo/project/app/controllers/articles_controller.rb 1 class ArticlesController < ApplicationController 2
before_action :set_article, only: [:show, :edit, :update, :destroy]
3 4
# GET /articles 199
Basic Computer Coding: Ruby
5
# GET /articles.json
6
def index
7
byebug
8
@articles = Article.find_recent
9 10
respond_to do |format|
This way you can move inside the file and see the code above the line where you added the byebug call. Finally, to see where you are in the code again you can type list= (byebug) list= [3, 12] in /PathTo/project/app/controllers/articles_controller.rb 3: 4:
# GET /articles
5:
# GET /articles.json
6:
def index
7:
byebug
=> 8:
@articles = Article.find_recent
9: 10:
respond_to do |format|
11:
format.html # index.html.erb
12:
format.json { render json: @articles }
(byebug)
7.3.3 The Context When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack. The debugger creates a context when a stopping point or an event is reached. The context has information about the suspended program which enables the debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and know the place where the debugged program is stopped At any time you can call the backtrace command (or its alias where) to print the backtrace of the application. This can be very helpful 200
Debugger
to know how you got where you are. If you ever wondered about how you got somewhere in your code, then backtrace will supply the answer. (byebug) where --> #0 ArticlesController.index at /PathToProject/app/controllers/articles_controller.rb:8 #1 ActionController::BasicImplicitRender.send_ action(method#String, *args#Array) at /PathToGems/actionpack-5.1.0/lib/action_controller/metal/ basic_implicit_render.rb:4 #2 AbstractController::Base.process_action(action#NilClass, *args#Array) rb:181
at /PathToGems/actionpack-5.1.0/lib/abstract_controller/base.
#3 ActionController::Rendering.process_action(action, *args) at /PathToGems/actionpack-5.1.0/lib/action_controller/metal/ rendering.rb:30 ... The current frame is marked with -->. You can move anywhere you want in this trace (thus changing the context) by using the frame n command, where n is the specified frame number. If you do that, byebug will display your new context. (byebug) frame 2 [176, 185] in /PathToGems/actionpack-5.1.0/lib/abstract_controller/ base.rb 176:
# is the intended way to override action dispatching.
177:
#
178: dispatched 179: 180: => 181: 182:
# Notice that the first argument is the method to be
# which is *not* necessarily the same as the action name. def process_action(method_name, *args) send_action(method_name, *args) end
183: 201
Basic Computer Coding: Ruby
184: Override
# Actually call the method associated with the action.
185: # this method if you wish to change how action methods are called, (byebug) The available variables are the same as if you were running the code line by line. After all, that’s what debugging is. You can also use up [n] and down [n] commands in order to change the context n frames up or down the stack respectively. n defaults to one. Up in this case is towards higher-numbered stack frames, and down is towards lower-numbered stack frames.
7.3.4 Threads The debugger can list, stop, resume and switch between running threads by using the thread command (or the abbreviated th). This command has a handful of options: thread: shows the current thread. thread list: is used to list all threads and their statuses. The current thread is marked with a plus (+) sign. thread stop n: stops thread n. thread resume n: resumes thread n. thread switch n: switches the current thread context to n. This command is very helpful when you are debugging concurrent threads and need to verify that there are no race conditions in your code.
7.3.5 Inspecting Variables Any expression can be evaluated in the current context. To evaluate an expression, just type it! This example shows how you can print the instance variables defined within the current context: [3, 12] in /PathTo/project/app/controllers/articles_controller.rb 3: 4: # GET /articles 202
Debugger
5:
# GET /articles.json
6:
def index
7:
byebug
=> 8:
@articles = Article.find_recent
9: 10:
respond_to do |format|
11:
format.html # index.html.erb
12:
format.json { render json: @articles
(byebug) instance_variables [:@_action_has_layout, :@_routes, :@_request, :@_response, :@_lookup_ context, :@_action_name, :@_response_body, :@marked_for_same_origin_ verification, :@_config] As you may have figured out, all of the variables that you can access from a controller are displayed. This list is dynamically updated as you execute code. For example, run the next line using next. (byebug) next [5, 14] in /PathTo/project/app/controllers/articles_controller.rb 5
# GET /articles.json
6
def index
7
byebug
8
@articles = Article.find_recent
9 => 10
respond_to do |format|
11
format.html # index.html.erb
12
format.json { render json: @articles }
13 14
end end
15 (byebug) 203
Basic Computer Coding: Ruby
And then ask again for the instance_variables: (byebug) instance_variables [:@_action_has_layout, :@_routes, :@_request, :@_response, :@_lookup_ context, :@_action_name, :@_response_body, :@marked_for_same_origin_ verification, :@_config, :@articles] Now @articles is included in the instance variables, because the line defining it was executed. You can also step into irb mode with the command irb (of course!). This will start an irb session within the context you invoked it. The var method is the most convenient way to show variables and their values. Let’s have byebug help us with it. (byebug) help var [v]ar Shows variables and its values var all
-- Shows local, global and instance variables of self.
var args
-- Information about arguments of the current scope
var const
-- Shows constants of an object.
var global
-- Shows global variables.
var instance -- Shows instance variables of self or a specific object. var local
-- Shows local variables in current scope.
This is a great way to inspect the values of the current context variables. For example, to check that we have no local variables currently defined: (byebug) var local (byebug) You can also inspect for an object method this way: (byebug) var instance Article.new @_start_transaction_state = {} @aggregation_cache = {} @association_cache = {} @attributes = ## 4: 5:
where(‘created_at > ?’, 1.week.ago).limit(limit) end
6: end (byebug) If we use next, we won’t go deep inside method calls. Instead, byebug will go to the next line within the same context. In this case, it is the last line of the current method, so byebug will return to the next line of the caller method. (byebug) next [4, 13] in /PathToProject/app/controllers/articles_controller.rb 4:
# GET /articles
5:
# GET /articles.json
6:
def index
7:
@articles = Article.find_recent
8: => 9:
respond_to do |format|
10:
format.html # index.html.erb
11:
format.json { render json: @articles }
12: 13:
end end
(byebug) If we use step in the same situation, byebug will literally go to the next Ruby instruction to be executed -- in this case, Active Support’s week method. (byebug) step [49, 58] in /PathToGems/activesupport-5.1.0/lib/active_support/core_ 206
Debugger
ext/numeric/time.rb 49: 50: # Returns a Duration instance matching the number of weeks provided. 51:
#
52:
#
53:
def weeks
=> 54:
2.weeks # => 14 days ActiveSupport::Duration.weeks(self)
55:
end
56:
alias: week: weeks
57: 58: # Returns a Duration instance matching the number of fortnights provided. (byebug) This is one of the best ways to find bugs in your code. You can also use step n or next n to move forward n steps at once.
7.3.7 Breakpoints A breakpoint makes your application stop whenever a certain point in the program is reached. The debugger shell is invoked in that line You can add breakpoints dynamically with the command break (or just b). There are 3 possible ways of adding breakpoints manually: break n: set breakpoint in line number n in the current source file. break file: n [if expression]: set breakpoint in line number n inside file named file. If an expression is given it must have evaluated to true to fire up the debugger. break class (.|\#)method [if expression]: set breakpoint in method (. and # for class and 207
Remember If you don’t want to run the program manually in debug mode, you can press the “Resume Button” on the tools panel to run to the next breakpoint, or finish the debug if there are no more breakpoints.
Basic Computer Coding: Ruby
instance method respectively) defined in class. The expression works the same way as with file: n. For example, in the previous situation [4, 13] in /PathToProject/app/controllers/articles_controller.rb 4:
# GET /articles
5:
# GET /articles.json
6:
def index
7:
@articles = Article.find_recent
8: => 9:
respond_to do |format|
10:
format.html # index.html.erb
11:
format.json { render json: @articles }
12: 13:
end end
(byebug) break 11 Successfully created breakpoint with id 1 Use info breakpoints to list breakpoints. If you supply a number, it lists that breakpoint. Otherwise it lists all breakpoints. (byebug) info breakpoints Num Enb What 1
y
at /PathToProject/app/controllers/articles_controller.rb:11
To delete breakpoints: use the command delete n to remove the breakpoint number n. If no number is specified, it deletes all breakpoints that are currently active. (byebug) delete 1 (byebug) info breakpoints No breakpoints. You can also enable or disable breakpoints: enable breakpoints [n [m [...]]]: allows a specific breakpoint list or all breakpoints to stop your program. This is the default state when you create a breakpoint. disable breakpoints [n [m [...]]]: make certain (or all) breakpoints have no effect on your program. 208
Debugger
7.3.8 Catching Exceptions The command catch exception-name (or just cat exception-name) can be used to intercept an exception of type exception-name when there would otherwise be no handler for it. To list all active catch points use catch.
7.3.9 Resuming Execution There are two ways to resume execution of an application that is stopped in the debugger: continue [n]: resumes program execution at the address where your script last stopped; any breakpoints set at that address are bypassed. The optional argument n allows you to specify a line number to set a one-time breakpoint which is deleted when that breakpoint is reached. finish [n]: execute until the selected stack frame returns. If no frame number is given, the application will run until the currently selected frame returns. The currently selected frame starts out the most-recent frame or 0 if no frame positioning (e.g up, down or frame) has been performed. If a frame number is given it will run until the specified frame returns.
7.3.10 Editing Two commands allow you to open code from the debugger into an editor: edit [file:n]: edit file named file using the editor specified by the EDITOR environment variable. A specific line n can also be given.
7.3.11 Quitting To exit the debugger, use the quit command (abbreviated to q). Or, type q! to bypass the Really quit? (y/n) prompt and exit unconditionally. A simple quit tries to terminate all threads in effect. Therefore your server will be stopped and you will have to start it again. 209
Basic Computer Coding: Ruby
7.3.12 Settings byebug has a few available options to tweak its behavior: (byebug) help se set Modifies byebug settings Boolean values take “on”, “off”, “true”, “false”, “1” or “0”. If you don’t specify a value, the boolean setting will be enabled. Conversely, you can use “set no” to disable them. You can see these environment settings with the “show” command. List of supported settings: autosave
-- Automatically save command history record on exit
autolist
-- Invoke list command on every stop
width
-- Number of characters per line in byebug’s output
autoirb
-- Invoke IRB on every stop
basename short paths
-- : information after every stop uses
linetrace
-- Enable line execution tracing
autopry
-- Invoke Pry on every stop
stack_on_error -- Display stack trace when `eval` raises an exception fullpath
-- Display full file names in backtraces
histfile -- File where cmd history is saved to. Default: ./.byebug_history listsize
-- Set number of source lines to list by default
post_mortem callstyle displayed
-- Enable/disable post-mortem mode -- Set how you want method call parameters to be
histsize -- Maximum number of commands that can be stored in byebug history savefile save
-- File where settings are saved to. Default: ~/.byebug_
210
Debugger
You can save these settings in an .byebugrc file in your home directory. The debugger reads these global settings when it starts. For example: set callstyle short set listsize 25
211
Basic Computer Coding: Ruby
SUMMARY ■
It doesn’t matter how easy a language is to use, it usually contains some bugs if it is more than a few lines long.
■
Here is a complete list of commands, which you can use while debugging your program.
■
It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment.
■
Rails makes use of the ActiveSupport::Logger class to write log information. Other loggers, such as Log4r, may also be substituted.
■
When something is logged, it’s printed into the corresponding log if the log level of the message is equal to or higher than the configured log level.
■
When running multi-user, multi-account applications, it’s often useful to be able to filter the logs using some custom rules.
■
Logging will always have a small impact on the performance of your Rails app, particularly when logging to disk.
■
When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem.
■
As soon as your application calls the byebug method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at the debugger’s prompt (byebug).
■
When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack.
■
The debugger can list, stop, resume and switch between running threads by using the thread command (or the abbreviated th).
■
Now you should know where you are in the running trace and be able to print the available variables. But let’s continue and move on with the application execution.
212
Debugger
■
A breakpoint makes your application stop whenever a certain point in the program is reached. The debugger shell is invoked in that line
■
The command catch exception-name (or just cat exceptionname) can be used to intercept an exception of type exception-name when there would otherwise be no handler for it.
■
To exit the debugger, use the quit command (abbreviated to q). Or, type q! to bypass the Really quit? (y/n) prompt and exit unconditionally.
213
Basic Computer Coding: Ruby
KNOWLEDGE CHECK 1.
2.
3.
4.
5.
Which of the following is supported by Ruby? a.
Multiple Programming Paradigms
b.
Dynamic Type System
c.
Automatic Memory Management
d.
All of the Mentioned
Which of the following features does the 2.0 version of ruby supports? a.
Method keyword arguments
b.
New literals
c.
Security fixes
d.
All of the mentioned
Which of the following languages syntax matches with the Ruby’s syntax? a.
Perl
b.
PHP
c.
Java
d.
Jquery
What is the extension used for saving the ruby file? a.
.ruby extension
b.
.rb extension
c.
.rrb extension
d.
None of the mentioned
Which of the following are valid floating point literal? a.
.5
b.
2
c.
0.5
d.
None of the mentioned
214
Debugger
REVIEW QUESTIONS 1.
Start the server without --debug, then call debugger in the code, and observe the output.
2.
Start the server with --debug and add a breakpoint to a controller method. Trigger that breakpoint and experiment with each of these commands: •
eval
•
list
•
next
•
step
•
continue
3.
Debugger is just a method. Try combining it with a conditional branch to only execute on a certain pathway through your code (like a nil input, for example).
4.
What you’re looking for is a debugger. With ruby 1.8, the ruby-debug gem provides the canonical one, and in ruby 1.9, the debugger gem provides a version of its successor that is well-maintained.
5.
Start your program with the gem loaded, for example ruby -rdebugger yourfile.rb, and you’ll have access to the debugger.
Check your Result 1. (d)
2. (d)
3. (a)
215
4. (b)
5. (c)
Basic Computer Coding: Ruby
REFERENCES 1.
https://www.tutorialspoint.com/ruby/ruby_debugger.htm
2.
https://www.wisegeek.com/what-is-debugging.htm
3.
Jonathan B. Rosenberg. How Debuggers Work: Algorithms, Data Structures, and Architecture. John Wiley & Sons.
4.
Sanjeev Kumar Aggarwal and M. Sarath Kumar (2003). “Debuggers for Programming Languages”. In Y.N. Srikant and Priti Shankar. The Compiler Design Handbook: Optimizations and Machine Code Generation. Boca Raton, Florida: CRC Press.
216
INDEX A Arbitrary delimiters 122 Array 6, 10, 11, 12, 27 Assignment operator 81, 82, 91 B Bang Methods 38 Blueprints 157 boolean values 83 Breakpoint 188, 191, 198, 207, 208, 209, 213, 215 C capitalize method 34 Character class 133, 134, 135
Classes 39 Class variables 49, 164 Collection of different elements 10 Comparison operators 78 computer languages 32, 59 concatenation 33, 53, 59 Conditional statements 66 Cross-platform interpreted language 2, 27 D Debugger 14 Debugging 185, 186, 193, 194 downcase method 35 Duck Typing 21
Basic Computer Coding: Ruby
E Executable code 178 F Fibonacci sequence 112 Finite number 105, 116 For loops 95, 105, 106, 116, 121 G global variables 49, 50, 59 H Hashes 11 I Impressive framework 13 Instance variables 47, 158, 159, 162, 173, 180 L length method 35 local variable 44, 45, 46, 47 Logical operators 65, 66, 68, 83, 85, 87 M Mathematical operators 172 Met class 179 Method Chaining 38 Modifier 123, 140, 150 O Object-oriented programming 169, 180 Operator 158, 172, 181 P
Pattern matching 122, 127, 141, 150 Programming language 2, 20, 21, 24, 25, 26, 27, 28 R Rails app 195, 212 Rails applications 13 Rails maintains 191, 212 Reflection Methods 37 Regex engine 133 Regular expression 122, 124, 126, 129, 130, 131, 132, 134, 139, 141, 143, 144, 148, 150, 151, 152 Replacement text 127, 147, 148, 150 Ruby 187, 188, 195, 206, 214 Ruby language 2, 20, 23, 24, 27, 28 Ruby operator 126 Ruby programmer 110 Ruby topics 129 S Separating characters 157 Smalltalk 2 String 33, 35, 39, 53, 59 String method 124 String representation 165, 166 Strings 2, 6, 8, 11, 31, 32, 59 Super classes 179 Symbol 11, 12 T Terminating application 193 Terminator 130, 150
Pattern literal 126, 150
218
Index
U Until loop 103, 104, 116 upcase method 35 V Value 156, 158, 160, 161, 173, 174, 175, 180
Variables 31, 32, 44, 46, 47, 49, 50, 52, 53, 59 W While loop 73, 75, 76, 77, 91, 99, 101, 102, 103, 104, 105, 106, 107, 116, 118 While statements 76, 91 Whitespace character 134, 138
219